Heroku SpringBoot ClassPathResource получить исключение FileNotFoundException - PullRequest
0 голосов
/ 21 января 2019

Я развернул проект SpringBoot на Heroku и получил исключение 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)

Я искал, если есть кто-нибудь, сталкивался с этой проблемой раньше, но я не мог найти решение.

Это структура каталогов на героку:

~/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 для хранения изображений, но это решение не рекомендуется Поэтому мне все еще нужен кто-то, у кого есть опыт развертывания приложения Spring Boot на Heroku, чтобы помочь мне.

1 Ответ

0 голосов
/ 04 марта 2019

Хотя мне не очень понятно, почему путь к файлу нельзя найти в приложении Spring, развернутом в Heroku, я пришел к другому подходу, который может быть полезен для других, имеющих такую ​​же проблему.Я использовал ресурсный подход Spring, создав класс конфигурации и внедрив содержимое файла в переменные с помощью аннотации @Value.Я раскрыл строковое значение содержимого файла с помощью метода Bean, который сделал чтение файла:

@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;
...