bolo-solo
bolo-solo copied to clipboard
非滴链图床上传的临时文件目录权限问题导致上传失败
版本: bolo 2.6
问题描述:
使用了七牛云的图床功能. 在测试时发现上传时会报错. 具体的报错内容如下:
[INFO 11-26 17:20:16 c.PicUploadProcessor 104] Uploading image [temp=/home/xxx/www/bolo-web/webapps/ROOT/image.png]
java.io.FileNotFoundException: /home/xxx/www/bolo-web/webapps/ROOT/image.png (Permission denied)
at java.io.FileOutputStream.open0(Native Method)
at java.io.FileOutputStream.open(FileOutputStream.java:270)
at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
at java.io.FileOutputStream.<init>(FileOutputStream.java:162)
at org.apache.commons.fileupload.disk.DiskFileItem.write(DiskFileItem.java:423)
at org.b3log.solo.bolo.pic.PicUploadProcessor.uploadPicture(PicUploadProcessor.java:106)
at org.b3log.solo.bolo.pic.PicUploadProcessor_$$_jvstbc2_51._d10uploadPicture(PicUploadProcessor_$$_jvstbc2_51.java)
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.b3log.latke.ioc.JavassistMethodHandler.invoke(JavassistMethodHandler.java:116)
at org.b3log.solo.bolo.pic.PicUploadProcessor_$$_jvstbc2_51.uploadPicture(PicUploadProcessor_$$_jvstbc2_51.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
查看现在的源代码发现这个上传时会先把文件保存到本地.再使用UploadUtils上传到对应的目标地址:
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File("temp/"));
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
Map okPic = new HashMap();
List<String> errFiles = new ArrayList<>();
try {
List<FileItem> itemList = upload.parseRequest(context.getRequest());
for (FileItem item : itemList) {
String name = item.getName();
String config;
try {
config = optionRepository.get(Option.ID_C_TUCHUANG_CONFIG).optString(Option.OPTION_VALUE);
} catch (Exception e) {
config = "hacpai";
}
final ServletContext servletContext = SoloServletListener.getServletContext();
final String assets = "/"; // 这里应该是直接使用了webapp的目录
String path = servletContext.getResource(assets).getPath();
path = URLDecoder.decode(path);
LOGGER.info("Uploading image [temp=" + path + name + "]");
File file = new File(path + name);
item.write(file);
item.delete();
try {
String url = UploadUtil.upload(config, file);
if (url.isEmpty()) {
url = "接口调用错误,请检查偏好设置-自定义图床配置,清除浏览器缓存并重启服务端。";
}
okPic.put(name, url);
} catch (Exception e) {
errFiles.add(name);
}
}
} catch (Exception e) {
e.printStackTrace();
}
出于安全考虑一般部署的webapp目录是不可写的. 我看原来是写到的是temp目录,不知为何后面修改为了webapp?
修改建议:
- 使用temp目录进行缓存.
- 如果后续的上传不是异步.(看代码确实不是) 建议直接使用apache的upload的fileItem 直接获取inputstream进行上传. 这样则少一次本地缓存.