当前位置: 代码迷 >> 综合 >> 1. java 接受 MultipartFile 对象
  详细解决方案

1. java 接受 MultipartFile 对象

热度:34   发布时间:2023-12-27 13:25:01.0

技巧:

一个接口有很多实现类,当调用 接口方法的时候,想知道 接口用的是哪个实现类,就用如下方法: 动态的获取接口用到的实现类

  OutputStream  outputStream = item.getOutputStream();// 查看 实际走的OutputStream 接口的  哪个实现类// class org.apache.tomcat.util.http.fileupload.DeferredFileOutputStreamSystem.out.println(outputStream.getClass());

1. springboot 

将 一个 文件 (字节数组) 从 A  系统 传个 B 系统

A 系统:

@GetMapping("test")public void test(HttpServletRequest request, HttpServletResponse response) throws IOException {// 生成字节数组 byte[] bytes = BarCodeUtils.generateBarCode128("DCTK_202108030001", 10.00, 0.3, true, false);MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();HttpHeaders header = new HttpHeaders();header.setContentType(MediaType.MULTIPART_FORM_DATA);HttpHeaders fileHeader = new HttpHeaders();// TODO// fileHeader.setContentType(MediaType.parseMediaType(uploadFile.getContentType()));fileHeader.setContentDispositionFormData("file", "123456789");Map result = null;// 创建字节流的   HttpEntity 对象HttpEntity<ByteArrayResource> fileEntity = new HttpEntity<>(new ByteArrayResource(bytes),fileHeader);// file  和 Controller 方法的 接参对应multiValueMap.add("file", fileEntity);// other params//multiValueMap.add("uploader", uploader);// B  系统的 访问链接String url = "http://127.0.0.1:8092/fileUpload";HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(multiValueMap, header);ResponseEntity<UploadFileOutput> resultFromB = restTemplate.postForEntity(url, httpEntity, UploadFileOutput.class);System.out.println(result.toString());System.out.println(result.toString());}

系统B 接受:

 /*** 上传文件* @param file 文件* @return*/@PostMapping(value = {"/fileUpload","uploadFile"})@ResponseBodypublic UploadFileOutput uploadFile(@RequestParam(value = "file") MultipartFile file, HttpServletResponse response) {try {byte[] bytes = file.getBytes();response.setContentType("image/png");InputStream in = new ByteArrayInputStream(bytes);} catch (IOException e) {e.printStackTrace();}return new UploadFileOutput("123456789","条形码");}

2. springcloud  

将 一个 文件(字节数组)从 A  系统 传个 B 系统

A系统:

// FeignClient 里 有  url 属性(IP 端口 ) ,指定 路由到 服务注册中心的哪台机器 
@FeignClient(value = "document-service", fallback = DocumentFeignClientFallBack.class)
public interface SystemFeignClient {/*** 上传图片* @param   @RequestHeader(name = "X-USER-INFO") String token,* @return*/@PostMapping(value = "/document/sys/fileUpload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)BaseResponse<UploadFileOutput> fileUpload(@RequestPart("file") MultipartFile file , @RequestParam("fileTypes")List<String> fileTypes,@RequestParam("maxBytes") String maxBytes);}

准备调用(生成byte 数组):

byte[] bytes = BarCodeUtils.generateBarCode(xsRefundFromDb.getXReimbursementno(), 10.00, 0.3, true, false);// 构建 MultipartFile 对象CustomMultipartFile multiFile =   new CustomMultipartFile(xsRefundFromDb.getXReimbursementno()+".jpg",bytes) ;UploadFileResult uploadFileResult = documentService.fileUpload(multiFile, Arrays.asList(".jpg"), "2345634565");

自定义 多媒体对象:

package com.longfor.crm3.finance.client.system.request;import org.apache.commons.io.FileUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;import javax.activation.MimetypesFileTypeMap;
import java.io.*;
import java.nio.file.Files;/*** @program: crm3-finance8* @description: 自定义多媒体文件* @author: guoyiguang* @create: 2021-08-03 20:46**/
public class CustomMultipartFile implements MultipartFile, Serializable {private String fileName;/*** 文件服务器只接受file参数*/private String attachmentName = "file";private    byte[] fileData;public CustomMultipartFile(String fileName,byte[] fileData) {this.fileName = fileName;this.fileData = fileData;this.attachmentName = attachmentName;}public CustomMultipartFile(String attachmentName, String fileName,byte[] fileData) {this.fileName = fileName;this.fileData = fileData;this.attachmentName = attachmentName;}@Overridepublic String getName() {return attachmentName;}@Overridepublic String getOriginalFilename() {return fileName;}@Overridepublic String getContentType() {return  new MimetypesFileTypeMap().getContentType(fileName);}@Overridepublic boolean isEmpty() {return fileData == null || fileData.length == 0;}@Overridepublic long getSize() {return fileData.length;}@Overridepublic byte[] getBytes() {return fileData;}// B 系统 Controller 里   MultipartFile  调用 getInputStream() 就是 调用// 这个被重写的方法获取流(原生的是 通过  路径去获取 文件流 )@Overridepublic InputStream getInputStream() {ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileData);return byteArrayInputStream;}@Overridepublic void transferTo(File dest) throws IOException {FileUtils.writeByteArrayToFile(dest, fileData);if (dest.isAbsolute() && !dest.exists()) {FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest.toPath()));}}
}

字节数组转MultipartFile 参考文章:

https://www.thinbug.com/q/18381928

也可以参考spring 代码:生成 MultipartFile 接口的  子类:

 @SneakyThrows@Testpublic void testList32() {// windows  C:\Users\dell\AppData\Local\TempFile location =  new  File(System.getProperty("java.io.tmpdir"));// sizeThreshold: The threshold (阈值 ) above which uploads will be stored on disk.// 封装了临时文件的全路径(包括文件名)// 定义磁盘 上 文件的 临时仓库(目录) FileItem item = new DiskFileItem("hh", "image/png",false, "fileName.jpg", 1, location);//  生成 临时文件 File 对象 和 临时文件名称 (以  .temp  后缀命名)OutputStream  outputStream = item.getOutputStream();// 查看 实际走的OutputStream 接口的  哪个实现类// class org.apache.tomcat.util.http.fileupload.DeferredFileOutputStreamSystem.out.println(outputStream.getClass());// DeferredFileOutputStream  父类的 write 方法// 写入内容  outputStream.write("DCTK_2021080300011234565432123456543234565432234543234543234543234554323456".getBytes(StandardCharsets.UTF_8));ApplicationPart part = new ApplicationPart(item, location);//  构建  MultipartFile  接口的 对象(spring的 StandardMultipartFile 是私有的, 所以 重新 创建一个类似的 类)MultipartFile multipartFile =  new StandardMultipartFile2(part,"hh");System.out.println(multipartFile);// multipartFile.getInputStream();String s = new String(multipartFile.getBytes());System.out.println(s);}

用到的实体类如下:

package com.example.demo.entity.spring;import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;/*** @program: springboot_01 spring 的  StandardMultipartFile 方法是私有的,所以重新写一个* @description:* @author: guoyiguang* @create: 2021-08-05 20:24**/
public class StandardMultipartFile2  implements MultipartFile, Serializable {private final Part part;private final String filename;public StandardMultipartFile2(Part part, String filename) {this.part = part;this.filename = filename;}@Overridepublic String getName() {return this.part.getName();}@Overridepublic String getOriginalFilename() {return this.filename;}@Overridepublic String getContentType() {return this.part.getContentType();}@Overridepublic boolean isEmpty() {return (this.part.getSize() == 0);}@Overridepublic long getSize() {return this.part.getSize();}@Overridepublic byte[] getBytes() throws IOException {return FileCopyUtils.copyToByteArray(this.part.getInputStream());}@Overridepublic InputStream getInputStream() throws IOException {return this.part.getInputStream();}@Overridepublic void transferTo(File dest) throws IOException, IllegalStateException {this.part.write(dest.getPath());}
}

缺点:生成了临时文件,需要运维人员定期维护

或者 通过 JVM 垃圾回收 , 监控 文件对象(或者MuiltpartFile 或者 其他对象)被回收了,通过虚引用 对象获取 临时目录,对相应的目录进行文件删除

B系统:

 @PostMapping(value = {"/fileUpload","uploadFile"})public UploadFileResult uploadFile(@RequestParam(value = "file") MultipartFile multipartFile, UploadFileDTO uploadFileDTO, HttpServletRequest request) {return null ;}

  相关解决方案