zoukankan      html  css  js  c++  java
  • SpringMvc上传文件遇到重复读取InputStream的问题


    文件上传配置:

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
      <property name="defaultEncoding" value="utf-8"></property>
      <property name="maxUploadSize" value="10485760000"></property>
      <property name="maxInMemorySize" value="40960"></property>
    </bean>
    

    Controller代码

    @RequestMapping("/file")
    @RestController
    public class HelloController {
      @Autowired
      private UploadService uploadService;
    
      @RequestMapping(value="/upload", method= RequestMethod.POST)
      public void upload(@RequestParam(value = "file", required = true) MultipartFile file) {
        String md5 = DigestUtils.md5Hex(file.getInputStream()); //使用commons-codec计算md5
        uploadService.upload(file.getInputStream());
      }
    }
    

    单元测试代码

    @ContextConfiguration(locations = "classpath*:META-INF/spring/spring-*.xml")
    @RunWith(SpringJUnit4ClassRunner.class)
    public class UploadServiceTests extends BaseTests {
        private static final Logger logger = LoggerFactory.getLogger(UploadServiceTests.class);
    
        @Autowired
        private UploadService uploadService;
    
        @Test
        public void upload() throws Exception {
          Integer num = new Random().nextInt(9999999);
          byte[] bytes = ("HelloWorld-" + num).getBytes();
          InputStream inputStream = new ByteArrayInputStream(bytes);
          String md5 = MD5Utils.getMD5(inputStream);
          uploadService.upload(inputStream);
        }
    }
    

    遇到问题:
    Controller代码可以正常上传,而单元测试代码上传只有0字节

    原因:
    在计算stream的md5时,已经将流的游标移动到了最后,如果不做任何处理直接使用,则无法再从流里读到字节。而Controller里的file.getInputStream()实际每次返回的并不是同一个流,也就是计算md5和传给upload方法的并不是同一个stream,所以Controller里的upload成功的取到了数据。单元测试的stream时手动创建的,计算md5和upload的都是同一个流,所以upload时流的游标已经在尾部了。

    修改单元测试代码为:

    InputStream inputStream = new ByteArrayInputStream(bytes);
    inputStream.mark(0);
    String md5 = MD5Utils.getMD5(inputStream);
    inputStream.reset();
    

    关于mark和reset的理解,可以参考通过mark和reset方法重复利用InputStream

  • 相关阅读:
    bzoj [Scoi2016]美味
    bzoj2200[Usaco2011 Jan]道路和航线
    bzoj3196 二逼平衡树 树套树(线段树套Treap)
    BZOJ3295 动态逆序对(树状数组套线段树)
    hdu 4819 Mosaic 树套树 模板
    bzoj2843 极地旅行社 LCT
    bzoj3874&2832 [Ahoi2014]宅男计划 模拟退火,三分
    bzoj3609 [Heoi2014]人人尽说江南好 博弈
    find命令进阶用法(一)
    find按照文件大小查找
  • 原文地址:https://www.cnblogs.com/liqipeng/p/7452685.html
Copyright © 2011-2022 走看看