com.yixan.base.web.controller.FileController Maven / Gradle / Ivy
package com.yixan.base.web.controller;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import com.yixan.base.common.api.file.model.FileAuthorization;
import com.yixan.base.common.api.file.model.FolderName;
import com.yixan.base.common.api.file.service.IFileService;
import com.yixan.base.common.error.ErrorCode;
import com.yixan.base.common.svc.file.service.LocalFileService;
import com.yixan.base.core.exception.ResultCode;
import com.yixan.base.core.exception.ServiceException;
import com.yixan.base.core.result.ResponseMessage;
import com.yixan.base.web.utils.FileIoUtil;
import com.yixan.base.web.utils.WebConfig;
import com.yixan.base.web.utils.WebUtil;
import com.yixan.tools.common.util.FileUtil;
import com.yixan.tools.common.util.StringUtil;
import com.yixan.tools.common.util.VerifyUtil;
/**
* 文件上传下载控制器
*
* @author zhaohuihua
* @version C01 2015-3-25
*/
@Controller
@RequestMapping("/actions/file")
public class FileController {
@Autowired
private IFileService fileService;
/**
* 文件上传
*
* @param file 上传的文件内容
* @param folder 根文件夹, 可为空(为空时由fileService.groupUseDefIfNull决定默认用files还是不要根文件夹)
* @param filename 文件名, 用来获取文件扩展名
* @return
*/
@ResponseBody
@RequestMapping(value = "upload", method = RequestMethod.POST)
public ResponseMessage upload(@RequestParam("file") CommonsMultipartFile file, FolderName folder, String filename) {
try {
if (filename == null) {
filename = file.getName();
}
InputStream input = file.getInputStream();
long size = file.getSize();
String url = fileService.upload(folder, filename, input, size);
return new ResponseMessage(url);
} catch (ServiceException e) {
return new ResponseMessage(e);
} catch (IOException e) {
return new ResponseMessage(ResultCode.SERVER_INNER_ERROR);
}
}
/**
* 下载文件
* 文件扩展名必须在allow.download.suffix配置中
* 文件必须位于文件服务配置的文件夹或allow.download.folder配置中
*
* @param path 文件的保存路径
* @param filename 下载时浏览器提示的文件名(可为空,从保存路径中截取)
* @throws IOException
* @throws ServiceException
*/
@RequestMapping("download")
public void download(HttpServletRequest request, HttpServletResponse response, String path, String filename)
throws IOException, ServiceException {
if (VerifyUtil.isBlank(path)) {
throw new ServiceException(ResultCode.PARAMTER_NOT_NULL);
}
if (VerifyUtil.isBlank(filename)) {
filename = new File(path).getName();
}
// 1.获取要下载的文件的绝对路径
String realPath = getRealPath(path);
if (!new File(realPath).exists()) {
throw new ServiceException(ErrorCode.FILE_NOT_FOUND);
}
// 2.设置content-disposition响应头控制浏览器以下载的形式打开文件
response.setHeader("content-disposition", FileIoUtil.toAttachmentDesc(request, filename));
// 3.获取要下载的文件输入流
try (InputStream in = new FileInputStream(realPath);) {
// 3.1.通过response对象获取OutputStream流
OutputStream out = response.getOutputStream();
// 3.2.复制文件流数据
FileUtil.copy(in, out);
}
}
// 获取文件实际保存路径, 如果是文件服务保存的, 根据文件服务配置获取文件; 否则获取WEB服务根路径下的文件
private String getRealPath(String path) throws ServiceException {
String serverPath = WebUtil.getInstance().getWebRoot();
// 先判断文件路径是不是文件服务
LocalFileService fs = null;
if (fileService instanceof LocalFileService) {
LocalFileService lfs = (LocalFileService) fileService;
if (fileService.isInsideFile(path)) {
fs = lfs;
}
}
if (fs == null) { // WebRoot
if (StringUtil.isUrl(path)) {
throw new ServiceException(ResultCode.PARAMTER_VALUE_ERROR);
}
if (!isAllowDownload(path, false)) {
throw new ServiceException(ResultCode.FORBIDDEN);
}
return FileUtil.concat(serverPath, path);
} else { // FileService
if (!isAllowDownload(path, true)) {
throw new ServiceException(ResultCode.FORBIDDEN);
}
// baseUrl = http://img.xx.com/ 或 /filecenter/
String baseUrl = fs.getBaseUrl();
String relativePath = path.substring(baseUrl.length());
String savePath = fs.getSavePath();
if (FileUtil.isAbsolutePath(savePath)) { // 绝对路径
// savePath = /home/filecenter/
return FileUtil.concat(savePath, relativePath);
} else { // 相对路径
// savePath = ../filecenter/
return FileUtil.concat(serverPath, savePath, relativePath);
}
}
}
@ResponseBody
@RequestMapping("authorize")
public ResponseMessage authorize(FolderName group) {
try {
FileAuthorization authorization = fileService.authorize(group);
return new ResponseMessage(authorization);
} catch (ServiceException e) {
return new ResponseMessage(e);
}
}
/** 判断是否允许下载 **/
private boolean isAllowDownload(String path, boolean inFileService) {
boolean allowSuffix = false;
WebConfig config = WebConfig.getInstance();
// 判断文件名后缀
String[] suffixes = config.getArray("allow.download.suffix");
for (String suffix : suffixes) {
if (path.endsWith(suffix)) {
allowSuffix = true;
break;
}
}
// 判断文件夹
boolean allowFolder;
if (inFileService) {
allowFolder = true; // 文件服务路径下的都可以下载
} else {
allowFolder = false;
String[] folders = config.getArray("allow.download.folder", false);
if (folders == null || folders.length == 0) {
folders = new String[] { "assets" }; // 兼容旧版本
}
for (String folder : folders) {
if (path.startsWith(folder + "/") || path.startsWith("/" + folder + "/")) {
allowFolder = true;
break;
}
}
}
return allowSuffix && allowFolder;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy