我已经在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存储图像来解决此问题,但不建议使用此解决方案。因此,我仍然需要具有在Heroku上部署Spring Boot应用程序的经验的人来帮助我。
答案 0 :(得分:1)
尽管对于我来说,不是很清楚为什么无法在部署在Heroku上的Spring应用程序中获得文件路径,但我还是提出了另一种方法,该方法可能会对其他遇到相同问题的人有所帮助。通过创建配置类并通过@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;
}
}
批注将文件内容注入变量中,我利用了Spring的Resource方法。我已经通过读取文件的Bean方法公开了文件内容的字符串值:
@Autowired
然后,我通过@Autowired
@Qualifier("myfile")
public String myfile;
批注使用了文件字符串内容:
{{1}}