Spring MultipartResolver 或者 ServletFileUpload 冲突导致获取不到http数据/Multipart数据为空

如果不知道MultipartResolver 或者ServletFileUpload 的,请点击这里


如果同时使用了MultipartResolver 和ServletFileUpload,就会在iter.hasNext()返回false.然后整个循环就跳出去了。

if (isMultipart) {
            DiskFileItemFactory factory = new DiskFileItemFactory(1024 * 1024 * 20, null);
            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setHeaderEncoding("UTF-8");
            upload.setSizeMax(1024 * 1024 * 20);

            List<FileItem> fileItems = upload.parseRequest(req);
            Iterator<FileItem> iter = fileItems.iterator();
            // 这里获取不到任何FileItem
            while (iter.hasNext()) {
                FileItem item = (FileItem) iter.next();
                if (item.isFormField()) {
                    String name = item.getFieldName();
                    String value = item.getString("UTF-8");
                    request.put(name, value);
                } else {
                    byte[] filebytes = item.get();
                    if (StringUtils.isBlank(item.getName())) {
                        continue;
                    }
                    
                    request.put(item.getFieldName(), new String(filebyte, "utf-8"));
                }
            }
        }
}
整个问题产生的原因是Spring框架先调用了MultipartResolver 来处理http multi-part的请求。这里http multipart的请求已经消耗掉。后面又交给ServletFileUpload ,那么ServletFileUpload 就获取不到相应的multi-part请求。


如果帐前 卒想快速解决这个问题。解决方法是加入帐前卒的multipartResolver,来单独处理某些请求。这些请求需要特判。例如下面的代码:


package example;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.multipart.commons.CommonsMultipartResolver;

/**
 * @author 帐前卒
 */
public class MyMultipartResolver extends CommonsMultipartResolver {
    private String excludeUrls;   
    private String[] excludeUrlArray;
    
    public String getExcludeUrls() {
        return excludeUrls;
    }


    public void setExcludeUrls(String excludeUrls) {
        this.excludeUrls = excludeUrls;
        this.excludeUrlArray = excludeUrls.split(",");
    }


    /**
     * 这里是处理Multipart http的方法。如果这个返回值为true,那么Multipart http body就会MyMultipartResolver 消耗掉.如果这里返回false
     * 那么就会交给后面的自己写的处理函数处理例如刚才ServletFileUpload 所在的函数
     * @see org.springframework.web.multipart.commons.CommonsMultipartResolver#isMultipart(javax.servlet.http.HttpServletRequest)
     */
    @Override
    public boolean isMultipart(HttpServletRequest request) {
        for (String url: excludeUrlArray) {
            // 这里可以自己换判断
            if (request.getRequestURI().contains(url)) {
                return false;
            }
        }
        
        return super.isMultipart(request);
    }
     
}


然后在web.xml中这样写:

<bean id="multipartResolver" class="example.MyMultipartResolver">
<property name="excludeUrls" value="example"/>
<!-- url中带有example的http请求就不会被multipartResolver先解析-->
</bean>




  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果您的form-data中Content-Type是multipart/form-data,那么需要使用特殊的方式来解析参数值。 在Java Web开发中,获取multipart/form-data数据最常用的方式是使用Apache Commons Fileupload组件。以下是获取multipart/form-data数据的示例代码: ```java @PostMapping("/upload") public String handleFileUpload(HttpServletRequest request) throws Exception { boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart) { DiskFileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); List<FileItem> items = upload.parseRequest(request); for (FileItem item : items) { if (item.isFormField()) { // 处理普通表单项 String name = item.getFieldName(); String value = item.getString(); System.out.println(name + "=" + value); } else { // 处理文件上传 String name = item.getFieldName(); String fileName = item.getName(); long size = item.getSize(); InputStream inputStream = item.getInputStream(); // 处理文件流... } } } // 处理其他业务逻辑... } ``` 上面的代码中,首先判断请求是否是multipart/form-data类型,如果是,则使用DiskFileItemFactory和ServletFileUpload来解析请求中的参数值。 在循环中,使用FileItem对象的isFormField方法来判断当前参数是否是普通表单项,如果是,则可以通过getFieldName和getString方法来获取参数名和参数值。 如果当前参数是文件上传项,则可以通过getName、getSize和getInputStream方法来获取文件名、文件大小和文件流。 需要注意的是,FileItem对象只能被读取一次,如果您需要多次读取同一个参数值,请先将其缓存到内存或磁盘中。另外,关于文件上传的安全性问题,建议您对上传的文件类型、大小、数量等做出限制,以防止恶意上传。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值