赞
踩
最近遇到一个和第三方系统系统对接,碰到的一个附件问题,由于没有指定标准,导致被牵着鼻子走,浪费了大量的时间,话不多说,上问题,及解决方法
遇到的问题:第三方系统推送附件,我这边使用MultipartFile 进行接收,是没问题的,但是一直出现附件上传服务器上下载下来打不开损坏了。后来想了一个办法之间传过来一个压缩包我接收保存,压缩包可以正常上传,下载,文件也没有问题,但是由于不能直接上传压缩包,只能是在代码里面解压压缩包,然后上传附件。
此时在解压的过程中也没有报错,但是又出现了老问题就是上传的附件下载下来损坏了,此时我就觉得可能是在读取文件的时候,转为MultipartFile对象的时候出问题(因为已经有写好的方法,直直接传参数就行),但是我通过接口测试工具测试还是可以上传压缩包,不能解压。
那会不会是文件读取的问题呢?
此时,我就将读取的文件输出到本地,果然,读取文件出现问题,那么问题已经定位到,哈哈哈
- @PostMapping("/createInstructions")
- public AjaxResult createInstructions(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "file") MultipartFile file) {
- if (oaService.mapping(request, response, file)) {
- return AjaxResult.success();
- }
- return AjaxResult.error();
- }
boolean mapping(HttpServletRequest request, HttpServletResponse response, MultipartFile file);
- @Transactional
- @Override
- public boolean mapping(HttpServletRequest request, HttpServletResponse response, MultipartFile file) {
- MultipartFile multipartFile = null;
-
- String originalFilename = file.getOriginalFilename() ;
- if (!originalFilename.endsWith(".zip")){
- throw new RuntimeException( originalFilename+"文件格式错误请上传.zip");
- }
- List<MultipartFile> multipartFileList = new ArrayList<>();
- ZipArchiveInputStream zipInputStream = null;
- BufferedInputStream bufferedInputStream = null;
- String zipEntryFile;
- try {
- zipInputStream = new ZipArchiveInputStream(file.getInputStream(), Charset.forName("UTF-8").toString());
- bufferedInputStream = new BufferedInputStream(zipInputStream) ;
- ZipEntry zipEntry;
- while ((zipEntry = zipInputStream.getNextZipEntry()) != null){
- if (zipEntry.isDirectory()) {
- continue;
- }else{
- zipEntryFile = zipEntry.getName();
-
- Assert.notNull(zipEntryFile,"压缩文件中子文件的名字格式不正确");
- byte[] bytes = new byte[(int)zipEntry.getSize()];
- bufferedInputStream.read(bytes,0,(int)zipEntry.getSize());
- InputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
-
- String contentType = MediaTypeFactory.getMediaType(zipEntryFile).orElse(MediaType.APPLICATION_OCTET_STREAM).toString();
- MultipartFile mockMultipartFile = new MockMultipartFile(zipEntryFile, zipEntryFile, contentType, byteArrayInputStream);
- multipartFileList.add(multipartFile);
-
- SysAttachment attachment = new SysAttachment();
- Long fileId = SnowFlake.getId();
- attachment.setFileid(fileId);
- String tempFilePath = tempPath + SnowFlake.getId() + File.separator;
- AjaxFileResult ajaxFileResult = sysAttachmentService.uploadServerFile(attachment, mockMultipartFile, tempFilePath);
- Integer state = ajaxFileResult.getState();
- if(state == 200){
- SysAttachment sysAttachment = sysAttachmentService.selectSysAttachmentById(fileId);
- OafileDetail detail = getOaDetail(sysAttachment,master.getId());
- logger.info("OA文件细明对象--------detail:{}", detail);
- oafileDetailMapper.insertSelective(detail); // oa文件细明对象
- logger.info("OA______________detail表插入成功-------string");
- }
-
- FileOutputStream fileOutputStream = null;
- try {
- fileOutputStream = new FileOutputStream(tempPath + zipEntryFile);
- byte[] buffer = new byte[1024];
- int length;
- while ((length = byteArrayInputStream.read(buffer)) > 0) {
- fileOutputStream.write(buffer, 0, length);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- multipartFileList.add(multipartFile);
- byteArrayInputStream.close();
- }
- }
- } catch ( IOException e){
- e.printStackTrace();
- }finally {
- if (bufferedInputStream!=null) {
- try {
- bufferedInputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (zipInputStream != null) {
- try {
- zipInputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
上述代码的问题:就是上传到服务器上下载下来损坏了,其实就是读取的时候出问题,优化后的代码如下:
- @Transactional
- @Override
- public boolean mapping(HttpServletRequest request, HttpServletResponse response, MultipartFile file) {
-
- try (ZipArchiveInputStream zipInputStream = new ZipArchiveInputStream(file.getInputStream(), Charset.forName("UTF-8").toString())) {
- ZipEntry zipEntry;
- while ((zipEntry = zipInputStream.getNextZipEntry()) != null) {
- if (zipEntry.isDirectory()) {
- continue;
- } else {
- String zipEntryFile = zipEntry.getName();
- Assert.notNull(zipEntryFile, "压缩文件中子文件的名字格式不正确");
-
- // 创建缓冲区
- byte[] buffer = new byte[4096];
- int bytesRead;
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-
- // 逐个读取文件内容
- while ((bytesRead = zipInputStream.read(buffer, 0, buffer.length)) != -1) {
- outputStream.write(buffer, 0, bytesRead);
- }
-
- // 创建MultipartFile对象
- byte[] fileBytes = outputStream.toByteArray();
- InputStream byteArrayInputStream = new ByteArrayInputStream(fileBytes);
- String contentType = MediaTypeFactory.getMediaType(zipEntryFile).orElse(MediaType.APPLICATION_OCTET_STREAM).toString();
- MultipartFile mockMultipartFile = new MockMultipartFile(zipEntryFile, zipEntryFile, contentType, byteArrayInputStream);
- byteArrayInputStream.close();
- outputStream.close();
-
- // 上传文件并处理结果
- SysAttachment attachment = new SysAttachment();
- Long fileId = SnowFlake.getId();
- attachment.setFileid(fileId);
- String tempFilePath = tempPath + SnowFlake.getId() + File.separator;
- AjaxFileResult ajaxFileResult = sysAttachmentService.uploadServerFile(attachment, mockMultipartFile, tempFilePath);
- Integer state = ajaxFileResult.getState();
- if (state == 200) {
- SysAttachment sysAttachment = sysAttachmentService.selectSysAttachmentById(fileId);
- OafileDetail detail = getOaDetail(sysAttachment, master.getId());
- logger.info("文件细明对象--------detail:{}", detail);
- oafileDetailMapper.insertSelective(detail); // oa文件细明对象
- logger.info("OA______________detail表插入成功-------string");
- }
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
-
-
- }
为什么这样写就好了?
字节读取问题:在读取zipEntry
的内容时,创建了一个大小为(int)zipEntry.getSize()
的字节数组,并使用bufferedInputStream.read
方法将字节数据读取到数组中。然而,这种方式可能会导致字节数组大小不足以容纳整个文件内容,从而导致文件损坏。为了解决这个问题,建议使用较小的缓冲区,逐个读取和写入文件内容,而不是一次性读取整个文件内容。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。