当前位置: 首页 > 面试题库 >

使用Spring WebFlow 2.4.0上传文件,未绑定参数

赫连飞沉
2023-03-14
问题内容

我正在使用Spring Framework 4.1.5,Spring Security 4.0.0.RC2,Spring Webflow
2.4.0.RELEASE和Tomcat 8.0.15。

我遵循了webflow 文档中的示例,但是无法在Form Bean中获取文件。

表格

    <form:form action="${flowExecutionUrl}" method="post" commandName="fileForm" enctype="multipart/form-data">
        <form:input type="file" value="" path="multipartFileUpload"/>
        <button type="submit" name="_eventId_forward"><spring:message code="signup.forward"/></button>
        <sec:csrfInput/>
    </form:form>

表单豆

public class FileForm implements Serializable {
    private static final long serialVersionUID = 1L;

    private transient MultipartFile multipartFileUpload;

    public MultipartFile getMultipartFileUpload() {
        return multipartFileUpload;
    }

    public void setMultipartFileUpload(final MultipartFile multipartFileUpload) {
        this.multipartFileUpload = multipartFileUpload;
    }
}

<view-state id="companyLogo" view="signup/company-logo" model="fileForm">
    <var name="fileForm" class="it.openex.pmcommonw.form.FileForm"/>
    <transition on="back" to="chooseProfile" bind="false" validate="false"/>
    <transition on="forward" to="companyInfo">
        <evaluate expression="userCommonBean.uploadImage(fileForm)"/>
    </transition>
</view-state>

支持对象

@Component
public class UserCommonBean {    
    public static void uploadImage(final FileForm fileForm) throws IOException, ServletException {
        fileForm.getMultipartFileUpload(); // always null!!!
    }
}

multipartResolver

@Bean
public CommonsMultipartResolver filterMultipartResolver() {
    final CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(10 * 1024 * 1024);
    multipartResolver.setMaxInMemorySize(1048576);
    multipartResolver.setDefaultEncoding("UTF-8");
    return multipartResolver;
}

Webflow配置

@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {

    @Autowired
    TilesViewResolver viewResolver;

    @Bean
    public FlowDefinitionRegistry flowRegistry() {
        return getFlowDefinitionRegistryBuilder()
            .setFlowBuilderServices(flowBuilderServices())
            .setBasePath("/WEB-INF/flows/")
            .addFlowLocation("signup.xml", UrlMap.SIGNUP_WEBFLOW)
            .addFlowLocation("user-edit.xml", UrlMap.PROFILE_EDIT_WEBFLOW)
            .build();
    }

    @Bean
    public FlowExecutor flowExecutor() {
        return getFlowExecutorBuilder(flowRegistry()).build();
    }

    @Bean
    public FlowHandlerAdapter flowHandlerAdapter() {
        final FlowHandlerAdapter flowHandlerAdapter = new FlowHandlerAdapter();
        flowHandlerAdapter.setFlowExecutor(flowExecutor());
        return flowHandlerAdapter;
    }

    @Bean
    public FlowHandlerMapping flowHandlerMapping() {
        final FlowHandlerMapping flowHandlerMapping = new FlowHandlerMapping();
        flowHandlerMapping.setFlowRegistry(flowRegistry());
        // this has to be less than -1
        flowHandlerMapping.setOrder(-2);
        return flowHandlerMapping;
    }

    @Bean
    public MvcViewFactoryCreator mvcViewFactoryCreator() {
        final MvcViewFactoryCreator mvcViewFactoryCreator = new MvcViewFactoryCreator();
        final List<ViewResolver> viewResolvers = Collections.singletonList(viewResolver);
        mvcViewFactoryCreator.setViewResolvers(viewResolvers);
        return mvcViewFactoryCreator;
    }

    @Bean
    public FlowBuilderServices flowBuilderServices() {
        return getFlowBuilderServicesBuilder().setViewFactoryCreator(mvcViewFactoryCreator())
            .setValidator(localValidatorFactoryBean()).build();
    }

    @Bean
    public LocalValidatorFactoryBean localValidatorFactoryBean() {
        return new LocalValidatorFactoryBean();
    }
}

在Tomcat的内部,context.xml我已经添加allowCasualMultipartParsing="true"

调试应用程序后,我可以在请求中看到文件数据,如果尝试将表单发布到普通控制器,则可以获取文件数据。

我也尝试删除了Spring Security,但在Spring WebFlow中仍然无法正常工作。

在requestParameters对象中,只有3个对象:

  • 执行
  • _eventid_forward
  • _csrf

日志中有一些相关的行

DEBUG 2015-03-13 18:03:15,053: org.springframework.web.multipart.support.MultipartFilter - Using MultipartResolver 'filterMultipartResolver' for MultipartFilter
DEBUG 2015-03-13 18:03:15,053: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'filterMultipartResolver'
DEBUG 2015-03-13 18:03:15,053: org.springframework.web.multipart.support.MultipartFilter - Resolving multipart request [/registrazione] with MultipartFilter
DEBUG 2015-03-13 18:03:15,060: org.springframework.web.multipart.commons.CommonsMultipartResolver - Found multipart file [multipartFileUpload] of size 469217 bytes with original filename [PoliziaMunicipale.png], stored in memory
....
DEBUG 2015-03-13 18:03:15,072: org.springframework.binding.mapping.impl.DefaultMapper - Beginning mapping between source [org.springframework.webflow.core.collection.LocalParameterMap] and target [it.openex.pmcommonw.form.FileForm]
DEBUG 2015-03-13 18:03:15,072: org.springframework.binding.mapping.impl.DefaultMapping - Adding mapping result [TargetAccessError@34bc31ea mapping = parameter:'execution' -> execution, code = 'propertyNotFound', error = true, errorCause = org.springframework.binding.expression.PropertyNotFoundException: Property not found, originalValue = 'e1s2', mappedValue = [null]]
DEBUG 2015-03-13 18:03:15,072: org.springframework.binding.mapping.impl.DefaultMapper - Completing mapping between source [org.springframework.webflow.core.collection.LocalParameterMap] and target [it.openex.pmcommonw.form.FileForm]; total mappings = 1; total errors = 1

multipartFileUpload属性未绑定在FileFormBean中。

我不确定它是否有用,但是org.springframework.webflow.context.servlet.HttpServletRequestParameterMap在第52行里面

if (request instanceof MultipartHttpServletRequest) {
        // ... process multipart data
    }

它失败了检查,因为请求是的实例
org.springframework.security.web.context.HttpSessionSecurityContextRepository$Servlet3SaveToSessionRequestWrapper

更新1

我可以确认multipartRequest.getFile(“ file”)也可以。

我无法启用org.springframework.web.multipart.support.MultipartFilter过滤器。

如果启用,multipartRequest是一个实例,StandardMultipartHttpServletRequest包含一个Servlet3SecurityContextHolderAwareRequestWrapper,包装一个Servlet3SaveToSessionRequestWrapper,最后包含一个DefaultMultipartHttpServletRequest我需要的multipartFile
无法访问的实例,但我无法获得它。

禁用它,因为multipartRequest成为的实例,所以我能够获得它
DefaultMultipartHttpServletRequest,但是没有文件验证,并且CommonsMultipartResolver不遵守maxUploadSize的限制。

另外,如果Tomcat因文件太大而超出Tomcat的maxPostSize限制而启动了异常,则该异常将被捕获,CustomAccessDeniedHandler因为其类型为org.springframework.security.access.AccessDeniedException,错误消息为Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.

查看请求对象,可以看到原始的Tomcat异常org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException。似乎没有适当的处理方法,但是,正如我所说,如果启用MultipartFilter,我将无法获取文件。


问题答案:

由于在Web应用程序中使用Spring Security 4.xx,我们遇到了同样的问题。问题是a
org.springframework.security.web.context.HttpSessionSecurityContextRepository$Servlet3SaveToSessionRequestWrapper不是的实例,org.springframework.web.multipart.MultipartHttpServletRequest但包含一个实例。强制转换将不起作用,并且ClassCastException会发生。

那就是为什么

if (request instanceof MultipartHttpServletRequest) {
    // ... process multipart data
}

永远不可能true

这个想法是org.springframework.web.multipart.support.StandardMultipartHttpServletRequest从本地人创建一个HttpServletRequest并且有效。

在我们的WebApp中,我们使用Spring Webflow文档第6.5.1节中指示的Pojo操作。调用POJO动作。

解决方法:

PojoAction.java

public String fileUpload(RequestContext requestContext) {
    final ServletExternalContext context = (ServletExternalContext) requestContext.getExternalContext();
    final MultipartHttpServletRequest multipartRequest = new StandardMultipartHttpServletRequest((HttpServletRequest)context.getNativeRequest());
    final File file = multipartRequest.getFile("file");
    fileUploadHandler.processFile(file); //do something with the submitted file
}

在flow.xml中,我们具有以下操作状态:

<action-state id="upload-action">
    <evaluate expression="pojoAction.uploadFile(flowRequestContext)"/>
    <transition to="show"/>
</action-state>

在这种情况下,不需要绑定到模型。希望对您有所帮助!

根据更新1

在web.xml中,必须在SpringSecurityFilterChain之前声明CSRF保护过滤器。

在我们的应用程序中,web.xml看起来像这样

    <filter>
        <filter-name>csrfFilter</filter-name>
        <filter-class>
            org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
        <async-supported>true</async-supported>
    </filter>
    <filter-mapping>
        <filter-name>csrfFilter</filter-name>
        <url-pattern>/*</url-pattern>
     </filter-mapping>

     <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>
           org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
      </filter>
      <filter-mapping>
         <filter-name>springSecurityFilterChain</filter-name>
         <url-pattern>/*</url-pattern>
         <dispatcher>REQUEST</dispatcher>
         <dispatcher>ERROR</dispatcher>
      </filter-mapping>


 类似资料:
  • 我使用的是Spring Framework 4.1.5,Spring Security 4.0.0.rc2,Spring Webflow 2.4.0.release和Tomcat 8.0.15。 我遵循了webflow文档中的示例,但无法在表单bean中获取文件。 表单 multipartResolver webflow配置 在Tomcat的中,我已经添加了 在requestParameters对

  • 问题内容: 我试图得到一个简单的文件上传机制的工作与快车4.0,但我不断收到对在体内。以下是相关代码: ..和随附的帕格代码: 解决方案 由于以下mscdex的响应,我已切换为使用而不是: 问题答案: 该模块仅处理JSON和urlencoded表单提交,而不是多部分提交(如果您要上传文件,情况就是如此)。 对于multipart,您需要使用诸如或或(multiparty / formidable是

  • 我正试图使用阿拉莫菲尔上传文件。使用文件()时,上传效果很好,但是,我似乎不知道如何使用选项? 这是我的测试: 我的状态代码是415? 此外,如何在上传中发送其他参数? 谢啦 编辑 我没有设置正确的内容类型: 仍然不知道如何发送附加参数随上传。

  • 我正在创建一个接口和链表的实现,如Java1.8: 接口没有编译器问题,但给出了错误其中我有

  • 问题内容: 我试图编写代码以将文件上传到PHP中的“媒体”文件夹。由于某些原因,它仍然无法正常工作。 这是执行代码: 这是我的表单代码: 任何想法为什么它可能无法正常工作? 编辑: 当我使用命令“ print_r($ _ FILES);”时,它显示: Array([file] => Array([name] =>屏幕截图2012-05-29 at 12.36.11 PM.png [type] =>

  • 问题内容: 我正在尝试为我的数据库实现一个非常基本的搜索引擎,其中用户可能包含各种信息。搜索本身包含几个联合选择,其中结果总是合并为3列。 但是,返回的数据是从不同的表中获取的。 每个查询都使用$ term进行匹配,并将其绑定到“:term”作为预备参数。 现在,该手册说: 调用PDOStatement :: execute()时,对于要传递给语句的每个值,必须包含一个唯一的参数标记。您不能在准备