bolo-solo icon indicating copy to clipboard operation
bolo-solo copied to clipboard

非滴链图床上传的临时文件目录权限问题导致上传失败

Open jianhong-li opened this issue 1 year ago • 0 comments

版本: 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?

修改建议:

  1. 使用temp目录进行缓存.
  2. 如果后续的上传不是异步.(看代码确实不是) 建议直接使用apache的upload的fileItem 直接获取inputstream进行上传. 这样则少一次本地缓存.

jianhong-li avatar Nov 26 '23 10:11 jianhong-li