Spring Boot升级后之文件上传坑

Spring Boot升级后之文件上传坑

SpringBoot又双叒叕出新版本啦,不加班的人们都在用SpringBoot了,What?你还在用xml配置,赶紧拥抱SpringBoot,以后迎娶白富美不是梦,最近一次系统改造需要将18年的老系统改造成SpringBoot,优雅发版,减少加班,走上云时代,拥抱微服务。。。二大,赶紧把这个幻想症患者带走

咳咳咳。。。还是说正事,在改造的过程中遇到通过流文件上传的接口全部挂了,你没听错是全挂了

怎么回事呢,听我娓娓道来,业务代码不外泄,所以来个模拟

一、首先创建一个简单的包含WEB依赖的SpringBoot项目

pom.xml内容:

jetty容器

<!-- Spring Boot 版本 -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>


<!-- Spring Boot web启动器 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <exclusions>
        <exclusion>
          <artifactId>spring-boot-starter-tomcat</artifactId>
          <groupId>org.springframework.boot</groupId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jetty</artifactId>
    </dependency>

tomcat容器:

<!-- Spring Boot 版本 -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>


<!-- Spring Boot web启动器 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

二、配置文件上传的文件大小限制

application.properties配置文件添加:

# 上传文件总的最大值
spring.servlet.multipart.max-request-size=10MB
# 单个文件的最大值
spring.servlet.multipart.max-file-size=10MB


三、单文件上传示例

1、度娘一波,从网上抄了一段代码,项目中肯定是抄的这段,transferTo用的风生水起

package com.foo.bar.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import java.io.File;
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@RestController
public class UploadController {

  @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  public Dict local(@RequestParam("file") MultipartFile file) {
    if (file.isEmpty()) {
      return Dict.create().set("code", 400).set("message", "文件内容为空");
    }
    String fileName = file.getOriginalFilename();
    String rawFileName = StrUtil.subBefore(fileName, ".", true);
    String fileType = StrUtil.subAfter(fileName, ".", true);
    final String filePath = "/Users/foobar/foo/bar/";
    String localFilePath = filePath + rawFileName + "-" + DateUtil.current(false) + "." + fileType;
    }
    try {
      file.transferTo(new File(localFilePath));
    } catch (IOException e) {
      log.error("【文件上传至本地】失败,绝对路径:{}", localFilePath, e);
      return Dict.create().set("code", 500).set("message", "文件上传失败");
    }

    log.info("【文件上传至本地】绝对路径:{}", localFilePath);
    return Dict.create().set("code", 200).set("message", "上传成功").set("data", Dict.create().set("fileName", fileName).set("filePath", localFilePath));
  }

}

点了一下运行,准备一杯咖啡,喝完就下班,这时你眉头一紧,看到了亮眼的文件上传失败

然后点开了可爱的idea

/private/var/folders/7c/c1m8c2h52mx_pz716jlmmsd80000gn/T/foo/bar/001-1597844615672.jpg (No such file or directory)

[21:43:40.705] ERROR com.foo.bar.controller.UploadController 38 local - 【文件上传至本地】失败,绝对路径:/foo/bar/001-1597844615672.jpg java.io.FileNotFoundException: /private/var/folders/7c/c1m8c2h52mx_pz716jlmmsd80000gn/T/foo/bar/001-1597844615672.jpg (No such file or directory)
	at java.io.FileOutputStream.open0(FileOutputStream.java) ~[?:1.8.0_211]
	at java.io.FileOutputStream.open(FileOutputStream.java:270) ~[?:1.8.0_211]
	at java.io.FileOutputStream.<init>(FileOutputStream.java:213) ~[?:1.8.0_211]
	at java.io.FileOutputStream.<init>(FileOutputStream.java:162) ~[?:1.8.0_211]
	at org.eclipse.jetty.util.MultiPartInputStreamParser$MultiPart.write(MultiPartInputStreamParser.java:329) ~[jetty-util-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile.transferTo(StandardMultipartHttpServletRequest.java:256) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at com.foo.bar.controller.UploadController.local(UploadController.java:36) ~[classes/:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_211]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_211]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_211]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_211]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:523) ~[jakarta.servlet-api-4.0.3.jar:4.0.3]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[jakarta.servlet-api-4.0.3.jar:4.0.3]
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:763) ~[jetty-servlet-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1631) ~[jetty-servlet-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:226) ~[websocket-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618) ~[jetty-servlet-9.4.29.v20200521.jar:9.4.29.v20200521]
	at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124) ~[druid-1.1.23.jar:1.1.23]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618) ~[jetty-servlet-9.4.29.v20200521.jar:9.4.29.v20200521]
	at com.foo.bar.filter.LogFilter.doFilterInternal(LogFilter.java:97) ~[classes/:?]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618) ~[jetty-servlet-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618) ~[jetty-servlet-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618) ~[jetty-servlet-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618) ~[jetty-servlet-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:549) ~[jetty-servlet-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:602) ~[jetty-security-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1610) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.ContextHandler.__doHandle(ContextHandler.java:1369) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:42020) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:489) ~[jetty-servlet-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1580) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1284) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.Server.handle(Server.java:501) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:556) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273) ~[jetty-server-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311) ~[jetty-io-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) ~[jetty-io-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104) ~[jetty-io-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336) ~[jetty-util-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313) ~[jetty-util-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171) ~[jetty-util-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:135) ~[jetty-util-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806) [jetty-util-9.4.29.v20200521.jar:9.4.29.v20200521]
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938) [jetty-util-9.4.29.v20200521.jar:9.4.29.v20200521]
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_211]

[21:43:40.719] INFO  com.foo.bar.filter.LogFilter 107 doFilterInternal - 请求URL:/upload, total time:9480 ms, responseCode:200, requestBody:file=001.jpg(1470037 byte), responseBody:{"code":500,"message":"文件上传失败"}
2020-08-19 21:52:12 JRebel: Reloading class 'com.foo.bar.controller.UploadController'.

你一点也不慌,再一次打开了度娘

多年code经验告诉你这是路径问题,然后你找到了这个

解决使用Spring Boot、Multipartfile上传文件路径错误问题

目录不存在,我就自己建一个,没毛病,一行代码的事

final String filePath = "/foo/bar/";
String localFilePath = filePath + rawFileName + "-" + DateUtil.current(false) + "." + fileType;
final File dirPath = new File(filePath);
if(!dirPath.exists()){
  dirPath.mkdirs();
}

热部署一波,喝了一口咖啡,在postman上优雅地点了send

你惊讶的发现,报错信息一点没变,你开始怀疑热部署工具是不是坏了,暴躁的重启了server.又点了一下send.你开始惶恐了,依然是这个错误。喝了一口咖啡,回忆往昔,这个上传方法,你已用了无数次,为何这一次不行了呢,是不是因为springboot版本的问题,你再一次点开了度娘,运气真不错,又找到了一个解决方案。

springboot升级导致文件上传自动配置/tmp目录问题解决

接着你开启了debug大法,在这行代码中陷入了沉思,你不敢相信自己的眼睛,

MultiPartInputStreamParser已经被标记为过时了

 沉思并不能解决问题,加上了

spring.servlet.multipart.location: /foo/bar

再试一次。。。

很遗憾还是报错了,只是这次错误有点稍微不一样,没有赶紧又去掉了


[22:52:31.957] INFO  org.springframework.boot.StartupInfoLogger 61 logStarted - Started BarApplication in 4.417 seconds (JVM running for 8.069)
[22:54:24.754] ERROR com.foo.bar.controller.UploadController 35 local - 【文件上传至本地】失败,绝对路径:/foo/bar/001-1597848801337.jpg java.io.FileNotFoundException: /foo/bar/foo/bar/001-1597848801337.jpg (No such file or directory) 

你发现度娘找到解决方案屁用没有,内心一度崩溃。。。关上电脑,今夜不加班。架构改造完,业务代码凉凉,现在知道为啥不让你动老系统了吧,知道错了吧。

第二天醒来,灵光一闪,求人不如求己,开始了一边阅读源码,一边debug

一个

再一个

你似乎看到了一道光,为什么不用下面这个 重载的方法呢,度娘了一圈,你发现竟然没有人用,你似乎要做第一个吃螃蟹的人了

加上了这行载入史册的代码:

file.transferTo(Paths.get(localFilePath));

成功了!

package com.foo.bar.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@RestController
public class UploadController {

  @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  public Dict local(@RequestParam("file") MultipartFile file) {
    if (file.isEmpty()) {
      return Dict.create().set("code", 400).set("message", "文件内容为空");
    }
    String fileName = file.getOriginalFilename();
    String rawFileName = StrUtil.subBefore(fileName, ".", true);
    String fileType = StrUtil.subAfter(fileName, ".", true);
    final String filePath = "/Users/foobar/foo/bar/";
    String localFilePath = filePath + rawFileName + "-" + DateUtil.current(false) + "." + fileType;
    final File dirPath = new File(filePath);
    if(!dirPath.exists()){
      dirPath.mkdirs();
    }
    try {
      file.transferTo(Paths.get(localFilePath));
    } catch (IOException e) {
      log.error("【文件上传至本地】失败,绝对路径:{}", localFilePath, e);
      return Dict.create().set("code", 500).set("message", "文件上传失败");
    }

    log.info("【文件上传至本地】绝对路径:{}", localFilePath);
    return Dict.create().set("code", 200).set("message", "上传成功").set("data", Dict.create().set("fileName", fileName).set("filePath", localFilePath));
  }

}

可不可以不实用transferTo方法,度娘大法开启,点开了第一个

MultipartFile File相互转化

MultipartFile转File

File file = new File(path); 

FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);  

这两个不就是一样的吗,So,还要用transferTo吗,这么坑比的方法,升级了Springboot版本就不能用了

		@Override
		public void transferTo(Path dest) throws IOException, IllegalStateException {
			FileCopyUtils.copy(this.part.getInputStream(), Files.newOutputStream(dest));
		}

彻底换掉这个坑比的transferTo,自己掌控流与文件,感觉真好

正确的文件上传方式:

1.流转文件

2.流转byte[]

package com.foo.bar.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import java.io.File;
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@RestController
public class UploadController {

  @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
  public Dict local(@RequestParam("file") MultipartFile file) {
    if (file.isEmpty()) {
      return Dict.create().set("code", 400).set("message", "文件内容为空");
    }
    String fileName = file.getOriginalFilename();
    String rawFileName = StrUtil.subBefore(fileName, ".", true);
    String fileType = StrUtil.subAfter(fileName, ".", true);
    String destFilePath = "/Users/foobar/foo/bar/" + rawFileName + "-" + DateUtil.current(false) + "." + fileType;
    final File destFile = new File(destFilePath);
    if(!destFile.getParentFile().exists()){
      destFile.getParentFile().mkdirs();
    }
    try {
      FileUtils.copyInputStreamToFile(file.getInputStream(), destFile);
    } catch (IOException e) {
      log.error("【文件上传至本地】失败,绝对路径:{}", destFilePath, e);
      return Dict.create().set("code", 500).set("message", "文件上传失败");
    }

    log.info("【文件上传至本地】绝对路径:{}", destFilePath);
    return Dict.create().set("code", 200).set("message", "上传成功").set("data", Dict.create().set("fileName", fileName).set("filePath", destFilePath));
  }

}

友情忠告,没事别动架构,别升级,别升级

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值