上传 和 下载
一:用户头像
/**
* 头像上传
*/
@Log(title = "用户头像", businessType = BusinessType.UPDATE)
@PostMapping("/avatar")
public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
{
if (!file.isEmpty())
{
LoginUser loginUser = getLoginUser();
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION); // IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" }
if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
{
AjaxResult ajax = AjaxResult.success();
ajax.put("imgUrl", avatar);
// 更新缓存用户头像
loginUser.getUser().setAvatar(avatar);
tokenService.setLoginUser(loginUser);
return ajax;
}
}
return error("上传图片异常,请联系管理员");
}
1.1 参数
@RequestParam("avatarfile") MultipartFile file @RequestParam 注解表明从请求参数中,获取名为 avatarfile 的文件,并且绑定到 MultipartFile类型的file变量上。
1.2 文件不为空
if (!file.isEmpty())
首先判断文件 , 不可以为空 。
1.3 下载方法
LoginUser loginUser = getLoginUser();
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
- 得到当前登录用户
- 调用 FileUploadUtils 的 upload 方法,传入三个个参数 一个是
-
- 下载路径,
- 第二个是 头像文件 ,
- 第三个是文件的类型。
- 返回的是 上传成功的文件名
1.3.1 upload 方法
/**
* 文件上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @param allowedExtension 上传文件类型
* @return 返回上传成功的文件名
* @throws FileSizeLimitExceededException 如果超出最大大小
* @throws FileNameLengthLimitExceededException 文件名太长
* @throws IOException 比如读写文件出错时
* @throws InvalidExtensionException 文件校验异常
*/
public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
InvalidExtensionException
{
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
assertAllowed(file, allowedExtension);
String fileName = extractFilename(file);
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
file.transferTo(Paths.get(absPath));
return getPathFileName(baseDir, fileName);
}
int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) //默认的文件名最大长度 100
{
throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
}
- 首先调用 MultipartFile 接口自己的 getOriginalFilename() 方法得到文件的原始名,然后得到它的长度
- 进行判断,如果大于文件名的最大长度 ,抛出 文件名称超长限制异常类
1.3.1.1 assertAllowed 方法
assertAllowed(file, allowedExtension); //
-
运用 assertAllowed 方法对文件进行一些校验
-
/** * 文件大小校验 * * @param file 上传的文件 * @return * @throws FileSizeLimitExceededException 如果超出最大大小 * @throws InvalidExtensionException */ public static final void assertAllowed(MultipartFile file, String[] allowedExtension) throws FileSizeLimitExceededException, InvalidExtensionException { long size = file.getSize(); if (size > DEFAULT_MAX_SIZE) { throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); } String fileName = file.getOriginalFilename(); String extension = getExtension(file); if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) { if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) { throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, fileName); } else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) { throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, fileName); } else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) { throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, fileName); } else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) { throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, fileName); } else { throw new InvalidExtensionException(allowedExtension, extension, fileName); } } } -
long size = file.getSize(); if (size > DEFAULT_MAX_SIZE) // DEFAULT_MAX_SIZE = 50 * 1024 * 1024L 50mb { throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024); } -
首先是进行文件大小的校验, 利用 MultipartFile 接口自己的 getSize 方法 获取文件的大小(以字节为单位),如果文件的大小超过50MB 就抛出 文件名大小限制异常类
-
String fileName = file.getOriginalFilename(); String extension = getExtension(file); -
获取文件原始名, 利用 getExtension 方法
-
获取文件名后缀
-
/** * 获取文件名的后缀 * * @param file 表单文件 * @return 后缀名 */ public static final String getExtension(MultipartFile file) { String extension = FilenameUtils.getExtension(file.getOriginalFilename()); if (StringUtils.isEmpty(extension)) { extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType())); //getContentType() :获取文件的内容类型(MIME 类型 , requireNonNull :如果参数为 null,则抛出空指针异常 } return extension; } -
判断文件的 类型
-
当 允许得文件类型不为空,并且 当前文件得扩展名,不在允许得范围内,就会进入 if 块
-
这里是根据不同的格式,抛出不同得文件类型得
-
if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) { if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) { throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension, fileName); } else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION) { throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension, fileName); } else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION) { throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension, fileName); } else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION) { throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension, fileName); } else { throw new InvalidExtensionException(allowedExtension, extension, fileName); } }运用了 isAllowedExtension 方法
/** * 判断MIME类型是否是允许的MIME类型 * * @param extension * @param allowedExtension * @return */ //IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" } public static final boolean isAllowedExtension(String extension, String[] allowedExtension) { for (String str : allowedExtension) { if (str.equalsIgnoreCase(extension)) { return true; } } return false; }通过遍历循环,来判断,文件得类型是不是符合 允许
1.3.1.2 extractFilename 方法 编码文件名
String fileName = extractFilename(file);
/**
* 编码文件名
*/
public static final String extractFilename(MultipartFile file)
{
return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
}
- 这里是把 文件名字格式进行编写
- 改为 。。/ 。。_。。. 文件格式 类似于 2025/01/09/example_12345 . jpg
- FilenameUtils . getBaseName 方法则从原始文件名中提取基本名称部分,即去掉扩展名后的部分。对于 example.jpg,它将返回 example。
- Seq.getId(Seq.uploadSeqType): 调用 Seq 类的 getId 方法,并传入 Seq.uploadSeqType 参数。这个方法可能会生成一个唯一的标识符,用于确保生成的文件名在同一时间内是唯一的。例如,它可能返回一个递增的数字序列或一个 UUID
1.3.1.3 getAbsoluteFile 方法
String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
确保了指定文件的父目录存在,并返回一个代表该文件绝对路径的 File 对象,为文件的后续操作提供了基础。
public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
{
File desc = new File(uploadDir + File.separator + fileName);
if (!desc.exists())
{
if (!desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
}
return desc;
}
File . separator 是一个与系统相关的路径分隔符,在 Windows 系统上是 \,在 Unix/Linux 系统上是 /
首先创建一个 文件对象
首先检查 desc 所代表的文件或目录是否存在。如果不存在,进一步检查该文件的父目录(即 desc. getParentFile())是否存在
如果父目录不存在,调用 mkdirs() 方法创建父目录及其所有必要的上级目录。mkdirs() 方法会创建指定路径中的所有不存在的目录。
- 例如,如果要创建的文件路径是 /a/b/c/example . jpg,而 /a 和 /a/b 目录都不存在,mkdirs() 会一次性创建 /a 和 /a/b 目录。
1.3.1.4 文件保存
file.transferTo(Paths.get(absPath));//absolutePath 绝对路径 :D:/ruoyi/uploadPath/avatar/2020/03/06/xxxx.jpg
Paths . get(absPath) 将绝对路径 absPath 转换为 Path 对象,Path 是 Java NIO.2 中用于处理文件路径的类。
transferTo 方法将上传的文件内容写入到由 Paths . get(absPath) 指定的文件路径中,从而完成文件的保存操作。
1.3.1.5 返回
return getPathFileName(baseDir, fileName);//baseDir = D:/ruoyi/uploadPath/avatar
//fileName = 2020/03/06/xxxx_202022324.jpg
截取路径,将路径变成 类似于 /profile/avatar/2024/12/25/詹姆随——black_ 20241225103235A001 . jpg 这样
public static final String getPathFileName(String uploadDir, String fileName) throws IOException
{
int dirLastIndex = RuoYiConfig.getProfile().length() + 1; //RuoYiConfig.getProfile(): D:/ruoyi/uploadPath
String currentDir = StringUtils.substring(uploadDir, dirLastIndex); //截取 D:/ruoyi/uploadPath/ 之后的部分
return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
}
1.3.2 数据库、缓存 更新
if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
{
AjaxResult ajax = AjaxResult.success();
ajax.put("imgUrl", avatar);
// 更新缓存用户头像
loginUser.getUser().setAvatar(avatar);
tokenService.setLoginUser(loginUser);
return ajax;
}
- 运用 userService 的 updateUserAvatar 方法,更新数据库中的头像的值
- 运用 tokenService的 setLoginUser方法,更新缓存中的用户信息
1.3.3 图片为空 , 报异常
return error("上传图片异常,请联系管理员");
二:下载
/**
* 通用下载请求
*
* @param fileName 文件名称
* @param delete 是否删除
*/
@GetMapping("/download")
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
{
try
{
if (!FileUtils.checkAllowDownload(fileName))
{
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
}
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
String filePath = RuoYiConfig.getDownloadPath() + fileName;
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, realFileName);
FileUtils.writeBytes(filePath, response.getOutputStream());
if (delete)
{
FileUtils.deleteFile(filePath);
}
}
catch (Exception e)
{
log.error("下载文件失败", e);
}
}
2.1 try —— catch 包裹
try{
}
catch (Exception e)
{
log.error("下载文件失败", e);
}
2.2 判断文件是否可以下载
if (!FileUtils.checkAllowDownload(fileName))
{
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
}
2.2.1 FileUtils 的 checkAllowDownload 方法
/**
* 检查文件是否可下载
*
* @param resource 需要下载的文件
* @return true 正常 false 非法
*/
public static boolean checkAllowDownload(String resource)
{
// 禁止目录上跳级别
if (StringUtils.contains(resource, ".."))
{
return false;
}
// 检查允许下载的文件规则
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
{
return true;
}
// 不在允许下载的文件规则
return false;
}
首先判断,文件名中,有无 .. (禁止目录上跳级别)
2.2.2 FileTypeUtils 的 getFileType方法 获取文件后缀
/**
* 获取文件类型
* <p>
* 例如: ruoyi.txt, 返回: txt
*
* @param fileName 文件名
* @return 后缀(不含".")
*/
public static String getFileType(String fileName)
{
int separatorIndex = fileName.lastIndexOf(".");
if (separatorIndex < 0)
{
return "";
}
return fileName.substring(separatorIndex + 1).toLowerCase();
}
2.2.3 允许下载的文件格式
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf
"pdf" };
2.3 生成文件名
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
这里生成一个 时间戳(170397480228040) 加上 原文件名_ 之后的名字拼接
2.4 生成文件路径
String filePath = RuoYiConfig.getDownloadPath() + fileName;
//RuoYiConfig.getDownloadPath()= D:/ruoyi/uploadPath/download/
生成一个 D:/ruoyi/uploadPath/download/ 固定开头加上 文件名的 文件路径
2.5 设置响应头
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, realFileName);
- response . setContentType(MediaType . APPLICATION_OCTET_STREAM_VALUE):设置响应的内容类型为application/octet-stream,表示这是一个二进制文件流,浏览器会将其作为下载文件处理。
- FileUtils . setAttachmentResponseHeader(response, realFileName):调用FileUtils类的setAttachmentResponseHeader方法,设置响应头,将文件名设置为realFileName,这样在下载时,浏览器显示的文件名就是realFileName。
/**
* 下载文件名重新编码
*
* @param response 响应对象
* @param realFileName 真实文件名
*/
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
{
String percentEncodedFileName = percentEncode(realFileName);
StringBuilder contentDispositionValue = new StringBuilder();
contentDispositionValue.append("attachment; filename=")
.append(percentEncodedFileName)
.append(";")
.append("filename*=")
.append("utf-8''")
.append(percentEncodedFileName);
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
response.setHeader("Content-disposition", contentDispositionValue.toString());
response.setHeader("download-filename", percentEncodedFileName);
}
-
/** * 百分号编码工具方法 * * @param s 需要百分号编码的字符串 * @return 百分号编码后的字符串 */ public static String percentEncode(String s) throws UnsupportedEncodingException { String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString()); return encode.replaceAll("\\+", "%20"); }
2.6 写入文件内容到响应
FileUtils.writeBytes(filePath, response.getOutputStream());
FileUtils 的 writeBytes 方法
/**
* 输出指定文件的byte数组
*
* @param filePath 文件路径
* @param os 输出流
* @return
*/
public static void writeBytes(String filePath, OutputStream os) throws IOException
{
FileInputStream fis = null;
try
{
File file = new File(filePath);
if (!file.exists())
{
throw new FileNotFoundException(filePath);
}
fis = new FileInputStream(file);
byte[] b = new byte[1024];
int length;
while ((length = fis.read(b)) > 0)
{
os.write(b, 0, length);
}
}
catch (IOException e)
{
throw e;
}
finally
{
IOUtils.close(os);
IOUtils.close(fis);
}
}
FileInputStream fis = null;
首先声明一个 空的输入流对象,用于后续读取内容
File file = new File(filePath);
if (!file.exists())
{
throw new FileNotFoundException(filePath);
}
通过 File 类根据传入的文件路径 filePath 创建一个 File 对象 file。然后检查该文件是否存在,如果不存在,抛出 FileNotFoundException 异常
fis = new FileInputStream(file);
byte[] b = new byte[1024];
int length;
while ((length = fis.read(b)) > 0)
{
os.write(b, 0, length);
}
创建一个 FileInputStream 对象 fis 来读取文件。定义一个大小为 1024 字节的字节数组 b 作为缓冲区。在 while 循环中,通过 fis.read(b) 从文件中读取数据到缓冲区 b 中,并将读取的字节数赋值给 length。只要读取的字节数大于 0,就表示读取到了数据,然后通过 os.write(b, 0, length) 将缓冲区 b 中从偏移量 0 开始长度为 length 的字节数据写入到输出流 os 中。
catch (IOException e)
{
throw e;
}
finally
{
IOUtils.close(os);
IOUtils.close(fis);
}
在 try - catch 块结束后,无论是否发生异常,都会执行 finally 块中的代码。这里使用 IOUtils . close 方法(推测 IOUtils 是一个工具类,提供了关闭流的方法)来关闭输出流 os 和文件输入流 fis,确保资源被正确释放,避免资源泄漏
2.7 判断是否删除
if (delete)
{
FileUtils.deleteFile(filePath);
}
如果delete参数为true,表示下载完成后需要删除服务器上的文件。调用FileUtils类的deleteFile方法删除指定路径(filePath)的文件。
/**
* 删除文件
*
* @param filePath 文件
* @return
*/
public static boolean deleteFile(String filePath)
{
boolean flag = false;
File file = new File(filePath);
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists())
{
flag = file.delete();
}
return flag;
}
三:上传
3.1、 上传单个
/**
* 通用上传请求(单个)
*/
@PostMapping("/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception
{
try
{
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath(); //D:/ruoyi/uploadPath/upload
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
String url = serverConfig.getUrl() + fileName;
AjaxResult ajax = AjaxResult.success();
ajax.put("url", url);
ajax.put("fileName", fileName);
ajax.put("newFileName", FileUtils.getName(fileName));
ajax.put("originalFilename", file.getOriginalFilename());
return ajax;
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
}
}
3.1.1 FileUploadUtils 的 upload 方法
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
/**
* 根据文件路径上传
*
* @param baseDir 相对应用的基目录
* @param file 上传的文件
* @return 文件名称
* @throws IOException
*/
public static final String upload(String baseDir, MultipartFile file) throws IOException
{
try
{
return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); //文件路径 、 文件 、 允许上传的文件类型
}
catch (Exception e)
{
throw new IOException(e.getMessage(), e);
}
}
允许的文件类型
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 视频格式
"mp4", "avi", "rmvb",
// pdf
"pdf" };
这里调用 upload 方法 和 头像上传 的方法是一致的 (参考1.3.1)
3.1.2 上传文件 url
String url = serverConfig.getUrl() + fileName;
/**
* 获取完整的请求路径,包括:域名,端口,上下文访问路径
*
* @return 服务地址
*/
public String getUrl()
{
HttpServletRequest request = ServletUtils.getRequest();
return getDomain(request);
}
public static String getDomain(HttpServletRequest request)
{
StringBuffer url = request.getRequestURL();
String contextPath = request.getServletContext().getContextPath();
return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
}
request . getRequestURL() 方法返回一个 StringBuffer 对象,它包含了完整的请求 URL,例如 example.com:8080/app/resourc…
request.getServletContext() . getContextPath() 获取当前 Web 应用的上下文路径。例如,如果应用部署在 /app 下,那么上下文路径就是 /app;如果是根部署,上下文路径就是空字符串 " "
url.delete(url.length() - request.getRequestURI().length(), url.length()):这部分代码从完整的请求 URL 中删除请求 URI 部分。request.getRequestURI() 返回请求的资源路径部分,例如 /app/resource。通过删除这部分,就得到了包含协议和主机名的基础部分,例如 example.com:8080
.append(contextPath):将获取到的上下文路径追加到上述基础部分之后
.toString():将最终构建好的 StringBuffer 对象转换为字符串并返回。例如,如果上下文路径是 /app,最终返回的可能是 example.com:8080/app
3.1.3 返回 成功响应对象
AjaxResult ajax = AjaxResult.success();
ajax.put("url", url);
ajax.put("fileName", fileName);
ajax.put("newFileName", FileUtils.getName(fileName));
ajax.put("originalFilename", file.getOriginalFilename());//返回文件的原始名
return ajax;
3.1.3.1 getName 方法 获取文件名称
/**
* 获取文件名称 /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png
*
* @param fileName 路径名称
* @return 没有文件路径的名称
*/
public static String getName(String fileName)
{
if (fileName == null)
{
return null;
}
int lastUnixPos = fileName.lastIndexOf('/');
int lastWindowsPos = fileName.lastIndexOf('\\');
int index = Math.max(lastUnixPos, lastWindowsPos);
return fileName.substring(index + 1);
}
首先检查传入的 fileName 是否为 null。如果是 null,直接返回 null,避免后续操作引发空指针异常。
分别查找字符串中最后一个 Unix 路径分隔符 / 和最后一个 Windows 路径分隔符 \ 的位置。lastIndexOf 方法返回指定字符在字符串中最后一次出现的位置,如果不存在则返回 -1
使用 Math.max 方法获取 lastUnixPos 和 lastWindowsPos 中的较大值。这是因为路径可能是 Unix 风格、Windows 风格,或者混合风格,通过取最大值可以确保获取到最后一个路径分隔符的位置
使用 substring 方法从 fileName 字符串中提取从 index + 1 位置开始到字符串末尾的子字符串,即文件名部分。例如,对于路径/profile/upload/2022/04/16/ruoyi.png,index 为最后一个/的位置,index + 1 就是文件名ruoyi.png的起始位置,提取后返回ruoyi.png
3.1.4 捕获异常,抛出异常信息
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
}
3.2、 上传多个
/**
* 通用上传请求(多个)
*/
@PostMapping("/uploads")
public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
{
try
{
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
List<String> urls = new ArrayList<String>();
List<String> fileNames = new ArrayList<String>();
List<String> newFileNames = new ArrayList<String>();
List<String> originalFilenames = new ArrayList<String>();
for (MultipartFile file : files)
{
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file);
String url = serverConfig.getUrl() + fileName;
urls.add(url);
fileNames.add(fileName);
newFileNames.add(FileUtils.getName(fileName));
originalFilenames.add(file.getOriginalFilename());
}
AjaxResult ajax = AjaxResult.success();
ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
return ajax;
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
}
}
遍历循环处理
遍历 files 列表中的每个文件:
调用 FileUploadUtils.upload(filePath, file) 方法将文件上传到指定路径,并获取上传后的新文件名。
通过 serverConfig.getUrl() 获取服务器的 URL,与新文件名拼接成文件的完整访问 URL,并添加到 urls 列表中。
将新文件名添加到 fileNames 列表中。
调用 FileUtils.getName(fileName) 方法从新文件名中提取仅文件名部分(去除路径),添加到 newFileNames 列表中。
将文件的原文件名添加到 originalFilenames 列表中。