• struts2安全插件struts2-secure-jakarta-multipart-parser-plugin引起的文件上传问题


    新项目的框架是ssh,用到了struts2的文件上传功能,但发现项目在eclipse启动后,只有第一次上传文件是ok的,以后上传就报

    2018-01-09 21:32:16 [http-nio-8080-exec-7] ERROR: com.cs.lexiao.admin.basesystem.component.core.AttachmentServiceImpl#save : Source '/home/vobile/workspace_trph/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/work/Catalina/localhost/lexiao-admin/upload_2df39ff2_d4c7_49ef_a521_925b0e85c43a_00000001.tmp' does not exist
    java.io.FileNotFoundException: Source '/home/vobile/workspace_trph/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/work/Catalina/localhost/lexiao-admin/upload_2df39ff2_d4c7_49ef_a521_925b0e85c43a_00000001.tmp' does not exist
        at org.apache.commons.io.FileUtils.copyFile(FileUtils.java:1004)
        at org.apache.commons.io.FileUtils.copyFile(FileUtils.java:968)
        at com.cs.lexiao.admin.basesystem.component.core.AttachmentServiceImpl.save(AttachmentServiceImpl.java:367)
        at com.cs.lexiao.admin.basesystem.component.core.AttachmentServiceImpl.save(AttachmentServiceImpl.java:217)
        at com.cs.lexiao.admin.basesystem.component.core.AttachmentServiceImpl$$FastClassByCGLIB$$99f22be.invoke(<generated>)
        at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
        at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
        at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:124)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:124)

    因为struts默会把文件放在/tmp1下面,生成了一个xxxx.tmp的临时文件,而报这个错是这个临时文件找不到,跟踪了下struts2的FileUploadInterceptor,

            Enumeration fileParameterNames = multiWrapper.getFileParameterNames();
            while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
                // get the value of this input tag
                String inputName = (String) fileParameterNames.nextElement();
    
                // get the content type
                String[] contentType = multiWrapper.getContentTypes(inputName);
    
                if (isNonEmpty(contentType)) {
                    // get the name of the file from the input tag
                    String[] fileName = multiWrapper.getFileNames(inputName);
    
                    if (isNonEmpty(fileName)) {
                        // get a File object for the uploaded File
                        File[] files = multiWrapper.getFiles(inputName);
                        if (files != null && files.length > 0) {
                            List<File> acceptedFiles = new ArrayList<File>(files.length);
                            List<String> acceptedContentTypes = new ArrayList<String>(files.length);
                            List<String> acceptedFileNames = new ArrayList<String>(files.length);
                            String contentTypeName = inputName + "ContentType";
                            String fileNameName = inputName + "FileName";
    
                            for (int index = 0; index < files.length; index++) {
                                if (acceptFile(action, files[index], fileName[index], contentType[index], inputName, validation)) {
                                    acceptedFiles.add(files[index]);
                                    acceptedContentTypes.add(contentType[index]);
                                    acceptedFileNames.add(fileName[index]);
                                }
                            }
    
                            if (!acceptedFiles.isEmpty()) {
                                Map<String, Object> params = ac.getParameters();
    
                                params.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()]));
                                params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));
                                params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));
                            }
                        }
                    } else {
                        if (LOG.isWarnEnabled()) {
                            LOG.warn(getTextMessage(action, "struts.messages.invalid.file", new String[]{inputName}));
                        }
                    }
                } else {
                    if (LOG.isWarnEnabled()) {
                        LOG.warn(getTextMessage(action, "struts.messages.invalid.content.type", new String[]{inputName}));
                    }
                }

    发现acceptedFiles有多个文件,准确的说是之前上传了多少个就有多少个,而我一次其实只上传了一个文件,而临时目录里也只有我这次上传的文件,对应到java代码里只会接受一个文件,默认取了第一个_00000001.tmp,而实际存在的是_00000004.tmp,那就报错了。

    为什么呢?当时怀疑是前端的问题,但没发现原因。后来我单独用postman向后端上传文件,发现问题依旧,说明是后端的问题。最后是注释掉了以前加的一个struts2的安全插件

    struts.xml

    <bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest"
               class="org.apache.struts.extras.SecureJakartaMultipartParser"
               name="secure-jakarta"
               scope="prototype"/> 
       
         <constant name="struts.multipart.parser" value="secure-jakarta"/>     

    把struts.xml里的这段注释掉就好了。

    那又是什么最终的原因呢?还没开始分析那个插件,待续。

     ----------------------------------

    配置改成scope="default"就好了

    喜欢艺术的码农
  • 相关阅读:
    线性回归和 逻辑回归 的思考(参考斯坦福 吴恩达的课程)
    数据结构算法基础-内部排序算法
    机器学习《test》
    day1.接口测试(概念、Postman、SoapUI、jmeter)
    SQL2000 3核6核 CUP 安装SP4
    SQL常用语句
    SQL SERVER 2000数据库置疑处理
    常用终端命令
    c++ 位操作
    计算机为什么用补码存储数据?
  • 原文地址:https://www.cnblogs.com/zjhgx/p/8253876.html
Copyright © 2020-2023  润新知