Java项目部署Heroku后存储文件提示找不到路径如何解决?
问题描述
我编写了一个通过MultipartFile存储logo图片的相关方法,本地环境运行完全正常,但将项目部署到Heroku云平台托管时出现报错。
Heroku控制台报错日志
2021-10-31T08:38:33.118740+00:00 app[web.1]: 2021-10-31 08:38:33.118 INFO 4 --- [io-47772-exec-9] com.Indoera.ecomProject.Utils.Utils : org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@60241167 2021-10-31T08:38:33.118885+00:00 app[web.1]: java.io.IOException: No such file or directory 2021-10-31T08:38:33.119038+00:00 app[web.1]: at java.io.UnixFileSystem.createFileExclusively(Native Method)
报错相关代码
public static String storeLogoPath(MultipartFile file) { String path = ""; try { path = "G:/MainWorkSpace/TestProjects/ecomProject/src/main/resources/static/img/storeLogo/"+file.getOriginalFilename(); File newFile = new File(path); newFile.createNewFile(); FileOutputStream myfile = new FileOutputStream(newFile); myfile.write(file.getBytes()); path ="/img/storeLogo/"+file.getOriginalFilename(); //PAth is setted mannualy to display images myfile.close(); logger.info("File should be saved now :: "); } catch (Exception e) { e.printStackTrace(); } logger.info("Path Returned is ::: " + path); return path; }
解决方案
你已经定位到核心原因是硬编码的Windows本地绝对路径在Heroku的Linux环境下不存在,除此之外还要注意Heroku的文件系统是临时可写的,所有写入的文件会在dyno重启、重新部署时自动清空,因此分两种场景给出解决方案:
1. 临时测试用方案(不适用生产环境)
放弃硬编码绝对路径,改为获取运行时目录,同时新增父目录存在性校验,修改后的代码示例如下:
public static String storeLogoPath(MultipartFile file) { String returnPath = ""; // 获取项目运行时的工作目录,拼接静态资源存储路径 String baseDir = System.getProperty("user.dir") + "/src/main/resources/static/img/storeLogo/"; try { File dir = new File(baseDir); // 父目录不存在则先递归创建 if (!dir.exists()) { dir.mkdirs(); } String fullPath = baseDir + file.getOriginalFilename(); File newFile = new File(fullPath); newFile.createNewFile(); // 使用try-with-resources自动关流,避免异常场景流泄漏 try (FileOutputStream myfile = new FileOutputStream(newFile)) { myfile.write(file.getBytes()); } returnPath = "/img/storeLogo/" + file.getOriginalFilename(); logger.info("File should be saved now :: "); } catch (Exception e) { e.printStackTrace(); } logger.info("Path Returned is ::: " + returnPath); return returnPath; }
注意:该方案仅能临时解决报错,Heroku重启后所有上传的图片会丢失。
2. 生产可用方案
不要将上传的图片存储在Heroku服务器本地,改为存储到专门的对象存储服务中,流程如下:
- 开通任意对象存储服务,获取访问密钥
- 上传文件时直接将文件流提交到对象存储服务
- 存储服务返回可访问的图片公网链接,将该链接存入数据库即可
该方案不受Heroku临时文件系统限制,数据永久可访问。
内容的提问来源于stack exchange,提问作者shivam sharma
相关产品推荐
相关产品推荐

