评论

收藏

[Java] springboot打成jar后获取classpath下文件失败的解决方案

编程语言 编程语言 发布于:2021-11-14 18:10 | 阅读数:681 | 评论:0

这篇文章主要介绍了使用springboot打成jar后获取classpath下文件失败的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
springboot打成jar后获取classpath下文件
代码如下:
ClassPathResource resource = new ClassPathResource("app.keystore");
File file = resource.getFile();
FileUtils.readLines(file).forEach(System.out::println);
解决方式如下:
1. Spring framework
String data = "";
ClassPathResource cpr = new ClassPathResource("static/file.txt");
try {
  byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
  data = new String(bdata, StandardCharsets.UTF_8);
} catch (IOException e) {
  LOG.warn("IOException", e);
}
2.use a file
ClassPathResource classPathResource = new ClassPathResource("static/something.txt"); 
InputStream inputStream = classPathResource.getInputStream();
File somethingFile = File.createTempFile("test", ".txt");
try {
  FileUtils.copyInputStreamToFile(inputStream, somethingFile);
} finally {
  IOUtils.closeQuietly(inputStream);
}
Resource resource = new ClassPathResource("data.sql");
BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
reader.lines().forEach(System.out::println);
String content = new ClassPathResourceReader("data.sql").getContent();
@Value("${resourceLoader.file.location}")
  @Setter
  private String location; 
  private final ResourceLoader resourceLoader; 
public void readallfilesfromresources() {
     Resource[] resources;
 
    try {
      resources = ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources("classpath:" + location + "/*.json");
      for (int i = 0; i < resources.length; i++) {
        try {
        InputStream is = resources[i].getInputStream();
        byte[] encoded = IOUtils.toByteArray(is);
        String content = new String(encoded, Charset.forName("UTF-8"));
        }
      }
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
}
springboot-项目获取resources下文件碰到的问题(classPath下找不到文件和文件名乱码)
项目是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();
我使用的是第二种。
@PostMapping("/downloadTemplateFile")
  public JSONData downloadTemplateFile(HttpServletResponse response) {
    String filePath = "templateFile/test.xlsx";
    Resource resource = new ClassPathResource(filePath);//用来读取resources下的文件
    InputStream is = null;
    BufferedInputStream bis = null;
    OutputStream os = null;
    try {
      File file = resource.getFile();
      if (!file.exists()) {
        return new JSONData(false,"模板文件不存在");
      }
      is = new FileInputStream(file);
      os = response.getOutputStream();
      bis = new BufferedInputStream(is);
      //设置响应头信息
      response.setCharacterEncoding("UTF-8");
      this.response.setContentType("application/octet-stream; charset=UTF-8");
      StringBuffer contentDisposition = new StringBuffer("attachment; filename="");
      String fileName = new String(file.getName().getBytes(), "utf-8");
      contentDisposition.append(fileName).append(""");
      this.response.setHeader("Content-disposition", contentDisposition.toString());
      //边读边写
      byte[] buffer = new byte[500];
      int i;
      while ((i = bis.read(buffer)) != -1) {
        os.write(buffer, 0, i);
      }
      os.flush();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
      return new JSONData(false,"模板文件不存在");
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if(os != null) os.close();
        if(bis != null) bis.close();
        if(is != null) is.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return new JSONData("模板文件下载成功");
  }
高高兴兴的启动项目后发现还是找不到文件,错误日志:
java.io.FileNotFoundException: class path resource [templateFile/test.xlsx] cannot be resolved to URL because it does not exist
  at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:195)
  at org.springframework.core.io.AbstractFileResolvingResource.getFile(AbstractFileResolvingResource.java:129)
  at com.citycloud.parking.support.controller.operate.OperateBusinessUserController.downloadTemplateFile(OperateBusinessUserController.java:215)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
  at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
  at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
  at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
  at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
  at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
  at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
  at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
  at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
  at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
  at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:158)
  at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:126)
  at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:111)
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
  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>标签:
<build>
  <resources>
    <resource>
    <directory>src/main/java</directory>
    <includes>
      <include>**/*.properties</include>
      <include>**/*.xml</include>
    </includes>
    <!--是否替换资源中的属性-->
    <filtering>false</filtering>
    </resource>
    <resource>
    <directory>src/main/resources</directory>
    <includes>
      <include>**/*.properties</include>
      <include>**/*.xml</include>
      <include>**/*.yml</include>
      <include>**/Dockerfile</include>
      <include>**/*.xlsx</include>
    </includes>
    <!--是否替换资源中的属性-->
    <filtering>false</filtering>
    </resource>
  </resources>
</build>
重新启动,再到classPath下看,发现有了这个文件了,同时也能获取了。如果文件名为中文的话就会出现乱码的情况。
怎么解决文件名中文乱码?
Access-Control-Allow-Origin →*
Access-Control-Allow-Credentials →true
Access-Control-Allow-Headers →accessToken,Access-Control-Allow-Origin,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers
Access-Control-Allow-Methods →POST,GET,PUT,PATCH,DELETE,OPTIONS,HEAD
Access-Control-Max-Age →360
Content-disposition →attachment; filename="????????-??????????.xlsx"
Content-Type →application/octet-stream;charset=UTF-8
Transfer-Encoding →chunked
Date →Fri, 19 Apr 2019 06:47:34 GMT
上面是使用postman测试中文乱码response响应头相关信息。
后面怎么改都乱码,然后我就试着到浏览器中请求试试,结果发现只是postman的原因,只要文件名编码跟返回内容编码一致("Content-disposition"和“ContentType”)就行:
this.response.setContentType("application/octet-stream; charset=iso-8859-1");
StringBuffer contentDisposition = new StringBuffer("attachment; filename="");
String fileName = file.getName();
contentDisposition.append(fileName).append(""");
//设置文件名编码
String contentDispositionStr = new String(contentDisposition.toString().getBytes(), "iso-8859-1");
this.response.setHeader("Content-disposition", contentDispositionStr);
到此全部结束!
以上为个人经验,希望能给大家一个参考,也希望大家多多支持CodeAE代码之家
原文链接:https://blog.csdn.net/qq_27384769/article/details/99877083

关注下面的标签,发现更多相似文章