1. java 接受 MultipartFile 对象

技巧:

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

  OutputStream  outputStream = item.getOutputStream();
  
            // 查看 实际走的OutputStream 接口的  哪个实现类
            // class org.apache.tomcat.util.http.fileupload.DeferredFileOutputStream
            System.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"})
    @ResponseBody
    public 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;
    }

    @Override
    public String getName() {
        return attachmentName;
    }


    @Override
    public String getOriginalFilename() {
        return fileName;
    }

    @Override
    public String getContentType() {
        return  new MimetypesFileTypeMap().getContentType(fileName);
    }

    @Override
    public boolean isEmpty() {
        return fileData == null || fileData.length == 0;
    }

    @Override
    public long getSize() {
        return fileData.length;
    }

    @Override
    public byte[] getBytes() {
        return fileData;
    }
    // B 系统 Controller 里   MultipartFile  调用 getInputStream() 就是 调用
    // 这个被重写的方法获取流(原生的是 通过  路径去获取 文件流 )
    @Override
    public InputStream getInputStream() {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileData);
        return byteArrayInputStream;
    }

    @Override
    public 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
    @Test
    public void testList32() {

        // windows  C:\Users\dell\AppData\Local\Temp
        File 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.DeferredFileOutputStream
            System.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;
    }

    @Override
    public String getName() {
        return this.part.getName();
    }

    @Override
    public String getOriginalFilename() {
        return this.filename;
    }

    @Override
    public String getContentType() {
        return this.part.getContentType();
    }

    @Override
    public boolean isEmpty() {
        return (this.part.getSize() == 0);
    }

    @Override
    public long getSize() {
        return this.part.getSize();
    }

    @Override
    public byte[] getBytes() throws IOException {
        return FileCopyUtils.copyToByteArray(this.part.getInputStream());
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return this.part.getInputStream();
    }

    @Override
    public 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 ;
    }


版权声明:本文为qq_38807606原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。