此为历史版本和 IPFS 入口查阅区,回到作品页
Polk
IPFS 指纹 这是什么

作品指纹

base64字符串传递文件

Polk
·
前两天开发一个功能中涉及文件上传/下载功能,这是非常常见的一个功能,一般都是前端通过multipart/form-data的模式传递给后端,后端则通过MultipartFile接收即可。

但这次遇到一个问题,前端请求先到C端(所谓C端可以理解为服务端的入口层,所有请求都会先到达C端,再由C端下发给各种不同的服务,这样的好处是对于前端来说,不需要跟一堆的后端部门对接,只要跟C端对接就好了)

我们服务间的调用都是通过feign这个http框架,这也是跟随spring cloud一起火起来的一个框架。但也就是这个框架导致从C端通过feign透传调用下游的服务一直失败,各种问题。以往别的同事都是在C端直接把文件存到阿里的oss,然后获取文件的url,再把url传给下游服务,下游服务再通过url从阿里oss下载后再处理。
但我觉得这样做太复杂了,C端就不应该有额外的业务逻辑,尽量透传是最好的,所以一心想直接通过feign传文件。

当尝试了多种写法都无济于事的时候,突然想到百度的图片识别API不是把图片转成base64字符串传递给后台的嘛,于是我就想在C端通过MultipartFile接收后,
转成byte数组,再将byte数组转成base64字符串,再通过feign传base64字符串就毫无问题了。同样的下载文件也是如此,先从下游服务生成文件后,先转成base64字符串返回给C端,
C端再转成文件直接通过httpServletResponse输出文件流。

这是C端将MultipartFile转成base64的代码段,关键是把文件名和类型都传递下去了,下游生成MultipartFile的时候需要
````java
@PostMapping("/upload")
public ResultContentResponse<Long> upload(@RequestParam("file") MultipartFile file, @RequestParam("scene") String scene, @RequestParam("orgId") Integer orgId) throws IOException {
    BankCardValideUploadRequest req = new BankCardValideUploadRequest();
    //String encode = new BASE64Encoder().encode(file.getBytes());
    String encode = Base64.encodeBase64String(file.getBytes());
    req.setFile(encode);
    req.setScene(scene);
    req.setOrgId(orgId);
    req.setFileContentType(file.getContentType());
    req.setFileName(file.getOriginalFilename());

    BasicResponse<Long> upload = bankCardValidClient.upload(req);
}
````

这是下游的代码,把base64转回MultipartFile,BASE64DecodedMultipartFile是自己实现一个MultipartFile, 需要用到文件名和类型
````java
byte[] bytes = Base64.decodeBase64(request.getFile());
MultipartFile multipartFile = new BASE64DecodedMultipartFile(bytes, request.getFileName(), request.getFileContentType());
````

````java
public class BASE64DecodedMultipartFile implements MultipartFile {

    private byte[] imgContent;
    private String fileName;
    private String contentType;


    public BASE64DecodedMultipartFile(byte[] imgContent, String fileName, String contentType) {
        this.imgContent = imgContent;
        this.fileName = fileName;
        this.contentType = contentType;
    }


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

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

    @Override
    public String getContentType() {
        return contentType;
    }

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

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

    @Override
    public byte[] getBytes() throws IOException {
        return imgContent;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return new ByteArrayInputStream(imgContent);
    }

    @Override
    public void transferTo(File dest) throws IOException, IllegalStateException {
        new FileOutputStream(dest).write(imgContent);
    }
}
````

下载的时候将excel文件转成ByteArrayOutputStream
````java
ByteArrayOutputStream byteArrayOutputStream = ee.writeFileToByte();
String encode = Base64.encodeBase64String(byteArrayOutputStream.toByteArray());
result.setFile(encode);
result.setFileName(fileName);
````

再由C端输出excel
````java
@PostMapping("/result/download")
public void reslutDownload(@RequestBody @Valid BankCardDoValideRequest request, HttpServletRequest httpServletRequest, HttpServletResponse response) throws Exception {
    BasicResponse<BankCardDoValideDto> bankCardDoValideDtoBasicResponse = bankCardValidClient.reslutDownload(request);
    BankCardDoValideDto data = bankCardDoValideDtoBasicResponse.getData();
    OutputStream os = null;
    try {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("UTF-8");
        response.setDateHeader("Expires", 0L);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.setHeader("Pragma", "no-cache");
        if (httpServletRequest.getHeader("User-Agent").toUpperCase().indexOf("MSIE") > 0) {
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(data.getFileName(), "UTF-8"));
        } else {
            response.setHeader("Content-Disposition", "attachment;filename*=utf-8'zh_cn'" + URLEncoder.encode(data.getFileName(), "UTF-8"));
        }
        os = response.getOutputStream();
        byte[] bytes = Base64.decodeBase64(data.getFile());
        Workbook wb = WorkbookFactory.create(new ByteArrayInputStream(bytes));
        wb.write(os);
    } finally {
        if (os != null) {
            os.flush();
            os.close();
        }
    }
}
````


CC BY-NC-ND 2.0 授权