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('.')); } }