摘要:項目拋出了個異常,。所以我們需要添加個轉換器類這樣就能夠識別了總結感覺把文件上傳所能遇到的坑全踩了個變,心累。
pom包的配置
啟動項類修改org.springframework.boot spring-boot-starter-web
/** * 防止文件大于10M時Tomcat連接重置 * * @return */ @Bean public TomcatServletWebServerFactory tomcatEmbedded() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> { if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol>)) { ((AbstractHttp11Protocol>) connector.getProtocolHandler()).setMaxSwallowSize(-1); } }); return tomcat; }配置文件修改
# 禁用 thymeleaf 緩存 spring.thymeleaf.cache=false # 是否支持批量上傳 (默認值 true) spring.servlet.multipart.enabled=true # 上傳文件的臨時目錄 (一般情況下不用特意修改) spring.servlet.multipart.location= # 上傳文件最大為 1M (默認值 1M 根據自身業務自行控制即可) spring.servlet.multipart.max-file-size=10MB # 上傳請求最大為 10M(默認值10M 根據自身業務自行控制即可) spring.servlet.multipart.max-request-size=10MB # 文件大小閾值,當大于這個閾值時將寫入到磁盤,否則存在內存中,(默認值0 一般情況下不用特意修改) spring.servlet.multipart.file-size-threshold=0 # 判斷是否要延遲解析文件(相當于懶加載,一般情況下不用特意修改) spring.servlet.multipart.resolve-lazily=false file.upload.path: /file/upload單文件上傳
@PostMapping("/upload") public Mapupload(@RequestParam MultipartFile file) throws IOException { //創建本地文件 File localFile = new File(path, file.getOriginalFilename()); //把傳上來的文件寫到本地文件 file.transferTo(localFile); //返回localFile文件路徑 Map path = new HashMap<>(); path.put("path", localFile.getAbsolutePath()); return path; }
這時候系統將會出現FileNotFoundException,日志類似下面這樣:
java.io.FileNotFoundException:C:UserschengAppDataLocalTemp omcat.7543349588424487992.9000workTomcatlocalhostROOTfileupload mpfileupload1558332190813.jpg (系統找不到指定的路徑。)
這是什么原因呢?可以進入transferTo方法
@Override public void transferTo(File dest) throws IOException, IllegalStateException { this.part.write(dest.getPath()); if (dest.isAbsolute() && !dest.exists()) { // Servlet 3.0 Part.write is not guaranteed to support absolute file paths: // may translate the given path to a relative location within a temp dir // (e.g. on Jetty whereas Tomcat and Undertow detect absolute paths). // At least we offloaded the file from memory storage; it"ll get deleted // from the temp dir eventually in any case. And for our user"s purposes, // we can manually copy it to the requested location as a fallback. FileCopyUtils.copy(this.part.getInputStream(), Files.newOutputStream(dest.toPath())); } }
而后我們再進入write方法
@Override public void write(String fileName) throws IOException { File file = new File(fileName); if (!file.isAbsolute()) { file = new File(location, fileName); } try { fileItem.write(file); } catch (Exception e) { throw new IOException(e); } }
這時候我們看到如果file.isAbsolute()成立,也就是我們沒有使用絕對路徑,那么file = new File(location,fileName);會在原來的基礎上加上location路徑.這就是原因所在,可以通過修改絕對路徑解決
直接將file.upload.path修改為絕對路徑即可
在代碼中控制
@PostMapping("/upload") public Mapupload(@RequestParam MultipartFile file) throws IOException { //創建本地文件 String classpath = ResourceUtils.getURL("classpath:").getPath(); File localFile = new File(classpath + path, file.getOriginalFilename()); //把傳上來的文件寫到本地文件 file.transferTo(localFile); //返回localFile文件路徑 Map path = new HashMap<>(); path.put("path", localFile.getAbsolutePath()); return path; }
通過ResourceUtils.getURL("classpath:").getPath()獲得項目路徑,然后加上設置的相對路徑。
網絡上還有一種修改location值的方式,可以看 這篇博客但是我個人使用是一直不可以。
或者可以不使用transferTo,代碼如下
@PostMapping("/singleFileUpload") public String singleFileUpload(@RequestParam("file") MultipartFile file) throws IOException { byte[] bytes = file.getBytes(); Path filePath = Paths.get(path + file.getOriginalFilename()); Files.write(filePath, bytes); return file.getOriginalFilename(); }
Paths.get所使用的也是絕對路徑,如果您在Windows機器上使用了這種路徑(從/開始的路徑),那么路徑將被解釋為相對于當前驅動器,例如
/file/upload/1.txt
而您的項目位于D盤。那么這條路徑就會對應這條完整的路徑:
D:fileupload1.txt
為了簡便,以下代碼均是使用絕對路徑。
文件上傳控制器編寫 多文件上傳@PostMapping("/uploads") public Map多文件上傳+表單提交uploads(@RequestParam MultipartFile[] files) throws IOException { StringBuilder sb = new StringBuilder(); Map paths = new HashMap<>(); for (MultipartFile file : files) { //創建本地文件 File localFile = new File(path, file.getOriginalFilename()); //把傳上來的文件寫到本地文件 file.transferTo(localFile); sb.append(localFile.getAbsolutePath()).append(","); paths.put(file.getOriginalFilename(), localFile.getAbsolutePath()); } //返回localFile文件路徑 return paths; }
@PostMapping("/uploadsWithForm") public Map多文件上傳+Json數據提交uploadsWithForm(@RequestParam String tmpString, @RequestParam MultipartFile[] files) throws IOException { StringBuilder sb = new StringBuilder(); Map paths = new HashMap<>(); paths.put("tmpString", tmpString); for (MultipartFile file : files) { //創建本地文件 File localFile = new File(path, file.getOriginalFilename()); //把傳上來的文件寫到本地文件 file.transferTo(localFile); sb.append(localFile.getAbsolutePath()).append(","); paths.put(file.getOriginalFilename(), localFile.getAbsolutePath()); } //返回localFile文件路徑 return paths; }
@PostMapping(value = "/uploadsWithJson") public MapuploadsWithJson(@RequestPart("files") MultipartFile[] files, @RequestPart("jsonMap") Map jsonMap) throws IOException { StringBuilder sb = new StringBuilder(); Map paths = new HashMap<>(); System.out.println(jsonMap); for (MultipartFile file : files) { //創建本地文件 File localFile = new File(path, file.getOriginalFilename()); //把傳上來的文件寫到本地文件 file.transferTo(localFile); sb.append(localFile.getAbsolutePath()).append(","); paths.put(file.getOriginalFilename(), localFile.getAbsolutePath()); } paths.put("jsonMap", JsonUtils.obj2json(jsonMap)); //返回localFile文件路徑 return paths; }
呵呵,不好用對不對。項目拋出了個異常,HttpMediaTypeNotSupportedException。
WARN o.s.w.s.m.support.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type "application/octet-stream" not supported]
所以我們需要添加個轉換器類
@Component public class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter { /** * Converter for support http request with header Content-Type: multipart/form-data */ public MultipartJackson2HttpMessageConverter(ObjectMapper objectMapper) { super(objectMapper, MediaType.APPLICATION_OCTET_STREAM); } @Override public boolean canWrite(Class> clazz, MediaType mediaType) { return false; } @Override public boolean canWrite(Type type, Class> clazz, MediaType mediaType) { return false; } @Override protected boolean canWrite(MediaType mediaType) { return false; } }
這樣就能夠識別了
總結感覺把springboot文件上傳所能遇到的坑全踩了個變,心累。
如果需要項目代碼,可以去我的github中下載;具體代碼可以查看file.upload目錄
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/74556.html
摘要:頁面如下集成由于個人感覺原生的不太好看,網上提供了。 集成swagger pom包配置 io.springfox springfox-swagger2 2.9.2 io.springfox springfox-swagger-ui ${swagger.version} 添加Swagger配置文件 @Configuration @...
摘要:一從零開始環境搭建對于之前的框架的使用,各種配置文件一旦出錯之后錯誤難尋,這也是為什么被推上主流的原因,的配置簡單,說分鐘能從框架的搭建到運行也不為過現在更是微服務當道,所以在此總結下的一些知識,新手教程是一個基于和概念的項目自動化構建開源 SpringBoot2.x【一】從零開始環境搭建 對于之前的Spring框架的使用,各種配置文件XML、properties一旦出錯之后錯誤難尋,...
摘要:是一款基于的接口服務集成基礎框架,內部提供了框架的封裝集成,讓接口開發者完成開箱即用,不再為搭建接口框架而犯愁,從而極大的提高開發效率。 ApiBoot是一款基于SpringBoot1.x、SpringBoot2.x的接口服務集成基礎框架,內部提供了框架的封裝集成,讓接口開發者完成開箱即用,不再為搭建接口框架而犯愁,從而極大的提高開發效率。通過在我的SpringBoot系列教程中得到的...
摘要:使用腳本在服務器中啟動與停止項目首先項目需要引用的插件啟動項目腳本以項目名為為例需先執行停止項目腳本以上版本的插件發布為了規避指令沖突參數統一加上前綴包發布腳本為項目停止腳本以項目名為為例在項目中文件夾然 使用Maven腳本在Centos服務器中啟動與停止項目 首先項目需要引用Maven的SpringBoot插件 boot-repac...
摘要:再通過函數創建的之后,用來創建該的基本信息這些基本信息會展現在文檔頁面中。函數返回一個實例用來控制哪些接口暴露給來展現,本例采用指定掃描的包路徑來定義,會掃描該包下所有定義的,并產生文檔內容除了被指定的請求。 showImg(http://download.qfeoo.com/kotlin_springboot_logo.png); 這里有個地方需要注意,在測試WebFlux集成Swa...
閱讀 2161·2021-09-04 16:40
閱讀 1453·2021-08-13 15:07
閱讀 3605·2019-08-30 15:53
閱讀 3194·2019-08-30 13:11
閱讀 1069·2019-08-29 17:22
閱讀 1811·2019-08-29 12:47
閱讀 1469·2019-08-29 11:27
閱讀 2221·2019-08-26 18:42