Heroku SpringBoot ClassPathResource获取FileNotFoundException

问题描述 投票:1回答:1

我在Heroku上部署了一个SpringBoot项目,我得到了FileNotFoundException,即使它在本地运行完全正常。

这是代码:

@GetMapping(path = "/api/items/image/get/{file_name}")
public ResponseEntity<InputStreamResource> getItemImage(@PathVariable("file_name") String fileName) {
    // append "_thumbsnail" to file name
    fileName = fileName.split("\\.")[0] + "_thumbsnail." + fileName.split("\\.")[1];
    ClassPathResource imgFile = new ClassPathResource("item_image/" + fileName, getClass().getClassLoader());
    try {
        return ResponseEntity.ok().contentType(MediaType.IMAGE_PNG)
                .body(new InputStreamResource(imgFile.getInputStream()));
    } catch (IOException e) {
        e.printStackTrace();
        return ResponseEntity.badRequest().body(null);
    }
}

这是错误:

2019-01-21T14:29:15.221959+00:00 app[web.1]: java.io.FileNotFoundException: class path resource [item_image/1234567890128_thumbsnail.png] cannot be opened because it does not exist
2019-01-21T14:29:15.226272+00:00 app[web.1]: at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:180)
2019-01-21T14:29:15.226412+00:00 app[web.1]: at com.smartscan.api.controller.ItemAPIController.getItemImage(ItemAPIController.java:116)
2019-01-21T14:29:15.226419+00:00 app[web.1]: at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2019-01-21T14:29:15.226447+00:00 app[web.1]: at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
2019-01-21T14:29:15.226474+00:00 app[web.1]: at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2019-01-21T14:29:15.226502+00:00 app[web.1]: at java.lang.reflect.Method.invoke(Method.java:498)
2019-01-21T14:29:15.226531+00:00 app[web.1]: at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
2019-01-21T14:29:15.226557+00:00 app[web.1]: at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
2019-01-21T14:29:15.226594+00:00 app[web.1]: at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
2019-01-21T14:29:15.226621+00:00 app[web.1]: at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
2019-01-21T14:29:15.226648+00:00 app[web.1]: at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
2019-01-21T14:29:15.226674+00:00 app[web.1]: at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
2019-01-21T14:29:15.226699+00:00 app[web.1]: at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
2019-01-21T14:29:15.226755+00:00 app[web.1]: at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
2019-01-21T14:29:15.226816+00:00 app[web.1]: at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
2019-01-21T14:29:15.226822+00:00 app[web.1]: at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
2019-01-21T14:29:15.226853+00:00 app[web.1]: at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
2019-01-21T14:29:15.226882+00:00 app[web.1]: at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
2019-01-21T14:29:15.226884+00:00 app[web.1]: at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
2019-01-21T14:29:15.226891+00:00 app[web.1]: at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
2019-01-21T14:29:15.226919+00:00 app[web.1]: at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
2019-01-21T14:29:15.226941+00:00 app[web.1]: at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
2019-01-21T14:29:15.226970+00:00 app[web.1]: at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
2019-01-21T14:29:15.226999+00:00 app[web.1]: at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
2019-01-21T14:29:15.227006+00:00 app[web.1]: at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
2019-01-21T14:29:15.227045+00:00 app[web.1]: at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
2019-01-21T14:29:15.227058+00:00 app[web.1]: at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
2019-01-21T14:29:15.227059+00:00 app[web.1]: at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
2019-01-21T14:29:15.227084+00:00 app[web.1]: at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)

我曾经搜索过是否有人之前遇到此问题,但我找不到解决方案。

这是heroku上的目录结构:

~/target $ ls
classes         mvn-dependency-list.log
generated-sources   smart-scan-0.0.1-SNAPSHOT.jar
generated-test-sources  smart-scan-0.0.1-SNAPSHOT.jar.original
maven-archiver      test-classes
maven-status

这是我创建文件时的日志:

===== itemImageFolder: file:/app/target/smart-scan-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/item_image/1133113.png
2019-01-22T14:47:00.507783+00:00 app[web.1]: ====== Thumps nail created file:/app/target/smart-scan-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/item_image/1133113_thumbsnail.png

这是加载文件时的日志:

2019-01-22T14:48:04.287928+00:00 app[web.1]: ====== READING RESOURCE file:/app/target/smart-scan-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/item_image/1133113_thumbsnail.png
2019-01-22T14:48:04.291731+00:00 app[web.1]: java.lang.IllegalArgumentException: InputStream must not be null

我如何保存文件:

    URL itemImageFolder = getClass().getClassLoader().getResource("item_image/");
    System.out.println("===== itemImageFolder: " + itemImageFolder.getPath() + imagePath);
    Path rootLocation = Paths.get(itemImageFolder.getPath());
    if (Files.notExists(rootLocation)) {
        Files.createDirectories(rootLocation);
    }
    Files.copy(file.getInputStream(), Paths.get(itemImageFolder.getPath() + imagePath),
            StandardCopyOption.REPLACE_EXISTING);
    // create thumbs nail
    BufferedImage originalImage = ImageIO.read(new File(itemImageFolder.getPath() + imagePath));
    int type = originalImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : originalImage.getType();
    BufferedImage resizeImageJpg = resizeImage(originalImage, type);
    System.out.println(
            "====== Thumps nail created " + itemImageFolder.getPath() + barcode + "_thumbsnail." + extension);

    ImageIO.write(resizeImageJpg, extension,
            new File(itemImageFolder.getPath() + barcode + "_thumbsnail." + extension));

以及我如何加载文件:

fileName = fileName.split("\\.")[0] + "_thumbsnail." + fileName.split("\\.")[1];
System.out.println("====== READING RESOURCE " + getClass().getClassLoader().getResource("item_image/").getPath() + fileName);
InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("item_image/" + fileName);

更新:我已通过更改使用Blob来存储Image来解决此问题,但不建议使用此解决方案。所以我仍然需要有人在Heroku上部署Spring Boot应用程序的经验来帮助我。

spring-boot heroku resources classpath filenotfoundexception
1个回答
1
投票

虽然我不清楚为什么文件路径无法在Heroku上部署的Spring应用程序中获取,但我采用了另一种方法,可能对其他具有相同问题的人有所帮助。我已经使用Spring的资源方法,通过创建配置类并通过@Value注释将文件内容注入变量。我通过Bean方法公开了文件内容的String值,该方法读取了文件:

@Configuration
public class ResourceFiles {

    @Value("classpath:myfile.ext")
    private Resource myfile;

    @Bean(name = "myfile")
    public String myfile() {
        try (InputStream is = myfile.getInputStream()) {
            return StreamUtils.copyToString(is, Charset.forName("UTF-8"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

}

然后,我通过@Autowired注释使用了文件字符串内容:

@Autowired
@Qualifier("myfile")
public String myfile;
© www.soinside.com 2019 - 2024. All rights reserved.