Spring文件POST(JSON)下载, restTemplate.execute大文件流处理

java下载接口

@PostMapping(value = "/download")
public void download(@RequestBody DownloadReq req, HttpServletRequest request, HttpServletResponse response) {
    
    // 省略..........

    String path = new File(path).getAbsolutePath() + File.separator + req.getFileName();
    File file = new File(path);
    if (!file.exists()) {
        LOGGER.info("file:{}", file.getAbsolutePath());
        LOGGER.info("下载文件不存在");
    }
    response.reset();
    response.setContentType("application/octet-stream");
    response.setCharacterEncoding("utf-8");
    response.setContentLength((int) file.length());
    String fileInfoHear = String.format("attachment;filename=%s", req.getFileName());
    response.addHeader("Content-Disposition", fileInfoHear);
    String origin = request.getHeader("Origin");
    response.addHeader("Access-Control-Allow-Origin", origin);
    response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
    response.addHeader("Access-Control-Allow-Headers", "Content-Type");
    response.addHeader("Access-Control-Allow-Credentials", "true");
    // 让浏览器能访问到其它响应头
    response.addHeader("Access-Control-Expose-Headers","Content-Disposition");


    try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {
        byte[] buff = new byte[1024];
        OutputStream os = response.getOutputStream();
        int i = 0;
        while ((i = bis.read(buff)) != -1) {
            os.write(buff, 0, i);
            os.flush();
        }
        LOGGER.info("file:{}, 下载成功", file.getAbsolutePath());
    } catch (IOException e) {
        LOGGER.error("异常", e);
    }
    // 只能返回null 或者方法是void, 否则会导致下载流关闭
}

java调用下载接口

public void download(DownloadReq req, String targetPath) {
    Map<String, Object> params = new HashMap<>();
    params.put("id", req.getId());

    Path targetPathO = Paths.get(targetPath);
    //定义请求头的接收类型
    RequestCallback requestCallback = request -> {
        request.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
        // json参数
        request.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        request.getBody().write(JSON.toJSONString(params).getBytes());
    };

    ResponseExtractor<Void> responseExtractor = response -> {
        //对响应进行流式处理而不是将其全部加载到内存中
        Files.copy(response.getBody(), targetPathO, StandardCopyOption.REPLACE_EXISTING);
        return null;
    };
    // 省略代码.....
    restTemplate.execute(url, HttpMethod.POST, requestCallback, responseExtractor);
    log.info("下载文件:{}, 完成", req.getFileName());
}

前端调用下载接口

this.loading = true
axios({
  method: 'post',
  url: process.env.VUE_APP_BASE_API + '/download',
  data: {
      // json参数
      id: this.$data.id
  },
  responseType: 'blob',
  onDownloadProgress: (evt) => {
    // 对原生进度事件的处理, 会在浏览器下方弹出下载文件框
    this.setState({ progress: parseInt((evt.loaded / evt.total) * 100) });
  }
}).then(response => {
  let contentDisposition = response.headers['content-disposition'];  //从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
  let filename = contentDisposition.split("filename=")[1];

  // 将二进制流转为blob
  let data = response.data ;
  const blob = new Blob([data], { type: 'application/octet-stream' })
  if (window.navigator.msSaveBlobOrOpenBlob) {
    // 兼容IE,window.navigator.msSaveBlob:以本地方式保存文件
    window.navigator.msSaveBlob(blob, decodeURI(filename))
  } else {
    // 创建新的URL并指向File对象或者Blob对象的地址
    const blobURL = window.URL.createObjectURL(blob)
    // 创建a标签,用于跳转至下载链接
    const tempLink = document.createElement('a')
    tempLink.style.display = 'none'
    tempLink.href = blobURL
    tempLink.setAttribute('download', decodeURI(filename))
    // 兼容:某些浏览器不支持HTML5的download属性
    if (typeof tempLink.download === 'undefined') {
      tempLink.setAttribute('target', '_blank')
    }
    // 挂载a标签
    document.body.appendChild(tempLink)
    tempLink.click()
    document.body.removeChild(tempLink)
    // 释放blob URL地址
    window.URL.revokeObjectURL(blobURL)
  }
}).finally(() => {
  this.loading = false
})
Java后端可以使用HttpClient库来实现Post提交文件及参数的功能。示例代码如下: ```java CloseableHttpClient httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); // 添加文件 builder.addBinaryBody("file", file, ContentType.APPLICATION_OCTET_STREAM, fileName); // 添加参数 builder.addTextBody("param1", "value1", ContentType.TEXT_PLAIN); builder.addTextBody("param2", "value2", ContentType.TEXT_PLAIN); HttpEntity multipart = builder.build(); httpPost.setEntity(multipart); CloseableHttpResponse response = httpClient.execute(httpPost); ``` 其中,`url`是要提交到的服务端地址,`file`是要提交的文件,`fileName`是文件名。`param1`和`param2`是要提交的参数及其对应的值。 在服务端接收文件及参数时,可以使用Spring框架的`MultipartFile`来接收文件,使用`@RequestParam`来接收参数。示例代码如下: ```java @PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("param1") String param1, @RequestParam("param2") String param2) throws IOException { byte[] bytes = file.getBytes(); // 处理文件和参数 return "success"; } ``` 其中,`/upload`是服务端接收请求的地址,`file`是要接收的文件,`param1`和`param2`是要接收的参数。 注意,在服务端接收参数时,需要根据参数的类型来设置参数的`ContentType`。例如,如果参数是文本类型,则设置为`ContentType.TEXT_PLAIN`。如果参数是JSON类型,则设置为`ContentType.APPLICATION_JSON`。 以上就是Java后端HttpClient Post提交文件及参数的实现方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值