項目是spring-boot + spring-cloud 並使用maven 管理依賴。在springboot+maven項目下怎么讀取resources下的文件實現文件下載?
- 怎么獲取resources目錄下的文件?(相對路徑)
方法一:
File sourceFile = ResourceUtils.getFile("classpath:templateFile/test.xlsx"); //這種方法在linux下無法工作
方法二:
Resource resource = new ClassPathResource("templateFile/test.xlsx"); File sourceFile = resource.getFile();
我使用的是第二種。
1 @PostMapping("/downloadTemplateFile") 2 public JSONData downloadTemplateFile(HttpServletResponse response) { 3 String filePath = "templateFile/test.xlsx"; 4 Resource resource = new ClassPathResource(filePath);//用來讀取resources下的文件 5 InputStream is = null; 6 BufferedInputStream bis = null; 7 OutputStream os = null; 8 try { 9 File file = resource.getFile(); 10 if (!file.exists()) { 11 return new JSONData(false,"模板文件不存在"); 12 } 13 is = new FileInputStream(file); 14 os = response.getOutputStream(); 15 bis = new BufferedInputStream(is); 16 //設置響應頭信息 17 response.setCharacterEncoding("UTF-8"); 18 this.response.setContentType("application/octet-stream; charset=UTF-8"); 19 StringBuffer contentDisposition = new StringBuffer("attachment; filename=\""); 20 String fileName = new String(file.getName().getBytes(), "utf-8"); 21 contentDisposition.append(fileName).append("\""); 22 this.response.setHeader("Content-disposition", contentDisposition.toString()); 23 //邊讀邊寫 24 byte[] buffer = new byte[500]; 25 int i; 26 while ((i = bis.read(buffer)) != -1) { 27 os.write(buffer, 0, i); 28 } 29 os.flush(); 30 } catch (FileNotFoundException e) { 31 e.printStackTrace(); 32 return new JSONData(false,"模板文件不存在"); 33 } catch (IOException e) { 34 e.printStackTrace(); 35 } finally { 36 try { 37 if(os != null) os.close(); 38 if(bis != null) bis.close(); 39 if(is != null) is.close(); 40 } catch (IOException e) { 41 e.printStackTrace(); 42 } 43 } 44 return new JSONData("模板文件下載成功"); 45 }
高高興興的啟動項目后發現還是找不到文件,錯誤日志:
1 java.io.FileNotFoundException: class path resource [templateFile/test.xlsx] cannot be resolved to URL because it does not exist 2 at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:195) 3 at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:129) 4 at com.citycloud.parking.support.controller.operate.OperateBusinessUserController.downloadTemplateFile(OperateBusinessUserController.java:215) 5 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 6 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 7 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 8 at java.lang.reflect.Method.invoke(Method.java:498) 9 at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) 10 at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) 11 at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) 12 at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877) 13 at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783) 14 at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) 15 at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) 16 at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) 17 at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) 18 at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877) 19 at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) 20 at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) 21 at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) 22 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 23 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 24 at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 25 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 26 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 27 at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:158) 28 at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:126) 29 at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:111) 30 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 31 at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
因為我知道Resource resource = new ClassPathResource("templateFile/test.xlsx");就是到classPath*(注意這里有個*)下去找,然后就去項目本地的目錄下找classPath下是否有這個文件(maven的classPath在 “target\classes”目錄下),就發現並沒有這個文件在。
后面仔細想想這是Maven項目啊,所以就找pom.xml文件去看看,突然想起:springboot的maven默認只會加載classPath同級目錄下文件(配置那些),其他的需要配置<resources>標簽:
1 <build> 2 <resources> 3 <resource> 4 <directory>src/main/java</directory> 5 <includes> 6 <include>**/*.properties</include> 7 <include>**/*.xml</include> 8 </includes> 9 <!--是否替換資源中的屬性--> 10 <filtering>false</filtering> 11 </resource> 12 <resource> 13 <directory>src/main/resources</directory> 14 <includes> 15 <include>**/*.properties</include> 16 <include>**/*.xml</include> 17 <include>**/*.yml</include> 18 <include>**/Dockerfile</include> 19 <include>**/*.xlsx</include> 20 </includes> 21 <!--是否替換資源中的屬性--> 22 <filtering>false</filtering> 23 </resource> 24 </resources> 25 </build>
重新啟動,再到classPath下看,發現有了這個文件了,同時也能獲取了。如果文件名為中文的話就會出現亂碼的情況。
- 怎么解決文件名中文亂碼?
1 Access-Control-Allow-Origin →* 2 Access-Control-Allow-Credentials →true 3 Access-Control-Allow-Headers →accessToken,Access-Control-Allow-Origin,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers 4 Access-Control-Allow-Methods →POST,GET,PUT,PATCH,DELETE,OPTIONS,HEAD 5 Access-Control-Max-Age →360 6 Content-disposition →attachment; filename="????????-??????????.xlsx" 7 Content-Type →application/octet-stream;charset=UTF-8 8 Transfer-Encoding →chunked 9 Date →Fri, 19 Apr 2019 06:47:34 GMT
上面是使用postman測試中文亂碼response響應頭相關信息。
后面怎么改都亂碼,然后我就試着到瀏覽器中請求試試,結果發現只是postman的原因,只要文件名編碼跟返回內容編碼一致("Content-disposition"和“ContentType”)就行:
1 this.response.setContentType("application/octet-stream; charset=iso-8859-1"); 2 StringBuffer contentDisposition = new StringBuffer("attachment; filename=\""); 3 String fileName = file.getName(); 4 contentDisposition.append(fileName).append("\""); 5 //設置文件名編碼 6 String contentDispositionStr = new String(contentDisposition.toString().getBytes(), "iso-8859-1"); 7 this.response.setHeader("Content-disposition", contentDispositionStr);
到此全部結束!