| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 |
- package modules.upload;
- import com.jfinal.aop.Before;
- import com.jfinal.kit.StrKit;
- import com.jfinal.upload.UploadFile;
- import common.interceptor.LoginInterceptor;
- import common.interceptor.role.RequiredRoleInterface;
- import common.utils.http.MyController;
- import common.utils.http.MyRet;
- import modules.user.UserController;
- import java.io.File;
- import java.io.IOException;
- import java.nio.file.Files;
- import java.nio.file.StandardCopyOption;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.UUID;
- public class UploadController extends MyController {
- // 默认上传文件保存的基路径,可以从配置文件中读取
- private static final String DEFAULT_UPLOAD_BASE_PATH = System.getenv("UPLOAD_BASE_PATH");
- // 默认的URL访问基路径,可以从配置文件中读取
- private static final String DEFAULT_URL_BASE = System.getenv("URL_BASE") + "/uploads";
- /**
- * 上传一个文件的方法
- * 前端通过 multipart/form-data 方式,将文件字段命名为 "file" 上传
- */
- @Before(LoginInterceptor.class)
- @RequiredRoleInterface({UserController.ROLE_SUPER_ADMIN})
- public void uploadOneFile() {
- UploadFile uploadFile = getFile("file");
- if (uploadFile == null) {
- renderJson(MyRet.fail("请上传文件"));
- return;
- }
- File tempFile = uploadFile.getFile(); // 获取 JFinal 上传的临时文件
- // important: uploadFile instance is useful so we don't delete it directly.
- try {
- String today = new SimpleDateFormat("yyyyMMdd").format(new Date());
- String extension = getFileExtension(uploadFile.getOriginalFileName());
- String uniqueFileName = UUID.randomUUID().toString().replace("-", "") + extension;
- File destDir = new File(DEFAULT_UPLOAD_BASE_PATH, today);
- if (!destDir.exists()) {
- if (!destDir.mkdirs()) {
- throw new RuntimeException("创建目标目录失败: " + destDir.getAbsolutePath());
- }
- }
- File destFile = new File(destDir, uniqueFileName);
- // --- 核心修改部分 ---
- // 使用 Files.move() 进行移动操作
- // StandardCopyOption.REPLACE_EXISTING: 如果目标文件已存在,则替换掉它
- // StandardCopyOption.ATOMIC_MOVE: 尝试进行原子性移动,如果不支持原子性则回退到非原子性
- Files.move(tempFile.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
- // --- 核心修改部分结束 ---
- String accessUrl = DEFAULT_URL_BASE + "/" + today + "/" + uniqueFileName;
- renderJson(MyRet.ok("上传成功").setData(accessUrl));
- } catch (IOException e) { // 捕获 IOException,Files.move 可能会抛出
- // 移动失败,打印详细错误信息
- e.printStackTrace();
- renderJson(MyRet.fail("文件移动失败,请检查服务器日志: " + e.getMessage()));
- } catch (Exception e) { // 其他异常
- e.printStackTrace();
- renderJson(MyRet.fail("上传失败: " + e.getMessage()));
- } finally {
- // 无论成功失败,确保临时文件被删除
- // 如果 Files.move 成功,tempFile 会被删除
- // 如果 Files.move 失败,tempFile 仍然存在,需要手动删除
- if (tempFile != null && tempFile.exists()) {
- tempFile.delete();
- }
- }
- }
- /**
- * 获取文件扩展名
- * @param fileName 文件名
- * @return 扩展名,包含".",例如 ".jpg"
- */
- private String getFileExtension(String fileName) {
- if (StrKit.isBlank(fileName) || fileName.lastIndexOf('.') == -1) {
- return "";
- }
- return fileName.substring(fileName.lastIndexOf('.'));
- }
- }
|