|
|
package com.controller;
|
|
|
|
|
|
import java.io.File;
|
|
|
import java.io.IOException;
|
|
|
import java.util.Date;
|
|
|
import org.apache.commons.io.FileUtils;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.http.HttpHeaders;
|
|
|
import org.springframework.http.HttpStatus;
|
|
|
import org.springframework.http.MediaType;
|
|
|
import org.springframework.http.ResponseEntity;
|
|
|
import org.springframework.util.ResourceUtils;
|
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
import org.springframework.web.bind.annotation.RequestParam;
|
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
import com.annotation.IgnoreAuth;
|
|
|
import com.baomidou.mybatisplus.mapper.EntityWrapper;
|
|
|
import com.entity.ConfigEntity;
|
|
|
import com.entity.EIException;
|
|
|
import com.service.ConfigService;
|
|
|
import com.utils.R;
|
|
|
|
|
|
/**
|
|
|
* 文件管理系统控制器
|
|
|
* 核心功能:处理文件上传/下载请求,管理系统静态资源
|
|
|
* 安全策略:@IgnoreAuth 使下载接口可公开访问
|
|
|
*/
|
|
|
@RestController
|
|
|
@RequestMapping("file") // 基础访问路径 /file
|
|
|
public class FileController {
|
|
|
|
|
|
@Autowired
|
|
|
private ConfigService configService; // 配置服务(用于存储特殊文件路径)
|
|
|
|
|
|
// ======================== 文件上传接口 ========================
|
|
|
/**
|
|
|
* 文件上传服务
|
|
|
* 路径:POST /file/upload
|
|
|
* 参数:
|
|
|
* @RequestParam("file") MultipartFile file - 上传的文件对象
|
|
|
* String type - 文件类型标识(特殊处理标记)
|
|
|
* 流程:
|
|
|
* 1. 空文件校验 → 抛出自定义异常 EIException
|
|
|
* 2. 提取文件后缀名(fileExt)
|
|
|
* 3. 获取项目static资源目录路径
|
|
|
* 4. 在static下创建upload目录(不存在时自动创建)
|
|
|
* 5. 生成时间戳文件名(避免重名覆盖)
|
|
|
* 6. 保存文件到服务器
|
|
|
* 7. 特殊类型文件(type="1")更新系统配置
|
|
|
* 返回值:R.ok().put("file", fileName) 返回新文件名
|
|
|
*/
|
|
|
@RequestMapping("/upload")
|
|
|
@IgnoreAuth // 允许匿名上传(根据需求谨慎设置)
|
|
|
public R upload(@RequestParam("file") MultipartFile file, String type) throws Exception {
|
|
|
// 1. 空文件校验
|
|
|
if (file.isEmpty()) {
|
|
|
throw new EIException("上传文件不能为空");
|
|
|
}
|
|
|
|
|
|
// 2. 提取文件后缀(如:png)
|
|
|
String fileExt = file.getOriginalFilename()
|
|
|
.substring(file.getOriginalFilename().lastIndexOf(".") + 1);
|
|
|
|
|
|
// 3. 获取static资源目录
|
|
|
File path = new File(ResourceUtils.getURL("classpath:static").getPath());
|
|
|
if (!path.exists()) path = new File("");
|
|
|
|
|
|
// 4. 创建upload目录
|
|
|
File uploadDir = new File(path, "/upload/");
|
|
|
if (!uploadDir.exists()) uploadDir.mkdirs();
|
|
|
|
|
|
// 5. 构建新文件名(时间戳防重名)
|
|
|
String fileName = new Date().getTime() + "." + fileExt;
|
|
|
File dest = new File(uploadDir, fileName);
|
|
|
|
|
|
// 6. 保存文件
|
|
|
file.transferTo(dest);
|
|
|
|
|
|
/*
|
|
|
* 热部署文件同步(开发环境专用)
|
|
|
* 解除注释并将路径改为本地项目static绝对路径
|
|
|
* 示例:FileUtils.copyFile(dest, new File("D:/project/src/main/resources/static/upload/"+fileName));
|
|
|
*/
|
|
|
|
|
|
// 7. 特殊文件类型处理(如人脸文件)
|
|
|
if ("1".equals(type)) {
|
|
|
// 查询或创建faceFile配置项
|
|
|
ConfigEntity faceConfig = configService.selectOne(
|
|
|
new EntityWrapper<ConfigEntity>().eq("name", "faceFile")
|
|
|
);
|
|
|
|
|
|
if (faceConfig == null) {
|
|
|
faceConfig = new ConfigEntity();
|
|
|
faceConfig.setName("faceFile");
|
|
|
faceConfig.setValue(fileName);
|
|
|
configService.insert(faceConfig);
|
|
|
} else {
|
|
|
faceConfig.setValue(fileName);
|
|
|
configService.updateById(faceConfig);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return R.ok().put("file", fileName);
|
|
|
}
|
|
|
|
|
|
// ======================== 文件下载接口 ========================
|
|
|
/**
|
|
|
* 文件下载服务
|
|
|
* 路径:GET /file/download?fileName={文件名}
|
|
|
* 流程:
|
|
|
* 1. 定位static/upload目录
|
|
|
* 2. 检查文件是否存在
|
|
|
* 3. 设置HTTP响应头:
|
|
|
* - ContentType: APPLICATION_OCTET_STREAM(二进制流)
|
|
|
* - Content-Disposition: attachment(触发浏览器下载)
|
|
|
* 4. 将文件转为字节流返回
|
|
|
* 安全说明:未做权限校验(@IgnoreAuth),生产环境需添加安全控制
|
|
|
*/
|
|
|
@IgnoreAuth // 允许匿名下载
|
|
|
@RequestMapping("/download")
|
|
|
public ResponseEntity<byte[]> download(@RequestParam String fileName) {
|
|
|
try {
|
|
|
// 1. 获取static目录路径
|
|
|
File staticDir = new File(ResourceUtils.getURL("classpath:static").getPath());
|
|
|
if (!staticDir.exists()) staticDir = new File("");
|
|
|
|
|
|
// 2. 定位upload目录
|
|
|
File uploadDir = new File(staticDir, "/upload/");
|
|
|
if (!uploadDir.exists()) uploadDir.mkdirs();
|
|
|
|
|
|
// 3. 构建目标文件
|
|
|
File targetFile = new File(uploadDir, fileName);
|
|
|
|
|
|
// 4. 文件存在性检查
|
|
|
if (targetFile.exists()) {
|
|
|
// 5. 设置响应头(触发下载)
|
|
|
HttpHeaders headers = new HttpHeaders();
|
|
|
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
|
|
headers.setContentDispositionFormData("attachment", fileName);
|
|
|
|
|
|
// 6. 返回文件字节流
|
|
|
return new ResponseEntity<>(
|
|
|
FileUtils.readFileToByteArray(targetFile),
|
|
|
headers,
|
|
|
HttpStatus.OK
|
|
|
);
|
|
|
}
|
|
|
} catch (IOException e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
// 7. 文件不存在或IO错误
|
|
|
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
|
|
}
|
|
|
}
|