技巧:
一个接口有很多实现类,当调用 接口方法的时候,想知道 接口用的是哪个实现类,就用如下方法: 动态的获取接口用到的实现类
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版权协议,转载请附上原文出处链接和本声明。