SpringBoot实现下载文件以及前台应当如何对接

SpringBoot实现文件下载以及前台对接方案

文件的下载返回:

这里用了一个ResponseEntity实体进行数据返回(当时就是不知道用什么对象返回文件,所以很恶心)。

请求头使用Content-Disposition,fileName标记返回时的文件名称;
ContentType使用octer-stream;
ContentLength...可以选择不填,长度如果填错了会报错
Body,返回文件的InputStream流

    fun downloadFile(@RequestBody fileId: Int): ResponseEntity<InputStreamResource> {

        val dest = fileService.getDownloadFile(fileId)

        return ResponseEntity.ok()
                .header("Content-Disposition", "attachment;filename=" + dest.name)
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .contentLength(dest.length())
                .body(InputStreamResource(dest.inputStream()))
    }

当然,我还看到了一种字节流的下载方式,也挺有趣的,但是用了之后好像出了点问题,就没用了(可行,但是数据不对)。

文件接收(百度用的一套代码)

    let filename = new Date().getTime().toString() + '.zip'
    let blob = new Blob([await downloadFile(res.data.data).data], { type: 'application/force-download' }) // 接收的是blob,若接收的是文件流,需要转化一下
    if (typeof window.chrome !== 'undefined') {
        // Chrome version
        let link = document.createElement('a')
        link.href = window.URL.createObjectURL(blob)
        link.download = filename
        link.click()

        // console.log(link)
    } else if (typeof window.navigator.msSaveBlob !== 'undefined') {
        // IE version
        let blob = new Blob([data], { type: 'application/force-download' })
        window.navigator.msSaveBlob(blob, filename)
    } else {
        // Firefox version
        let file = new File([data], filename, { type: 'application/force-download' })
        window.open(URL.createObjectURL(file))
    }

虽然做出来了,但是很多地方都不完美,我遇到了一堆非常恶心的事情:
因为这个是一个接口请求,只有请求完全结束(文件已经被下载下来之后),下载的文件才会突然显示。
这并不符合我的预期,也是一个非常糟糕的交互。

结局思路:

  1. 创建文件链接
  2. 开放文件下载接口,靠token和filepath进行下载

Q&A

为什么要写这篇文章

  • 作为一条孤龙来说,所有的解决方案都是自己去一点点翻查的。然后,网上居然一点类似的文章都没有!!

参考文章&视频

适用人群:一些和我一样不喜欢走按部就班的学习路径,选择自学,且只看目录的人们。。。


后来用了接口的形式实现了不跳转界面的下载(瞬间跳转一下,然后自动关上的那种,我有一个可以优化的思路,无需跳转的,等下次完成了断点下载功能的时候一起更新了)

原文地址:https://www.cnblogs.com/Arunoido/p/14824268.html