likes
comments
collection
share

从前后端代码看文件下载方式

作者站长头像
站长
· 阅读数 10

前言

在日常前端开发中文件导出,文件下载功能已经是屡见不鲜,正常碰到这个功能都是百度搜索文件下载然后复制代码,功能实现了,代码能跑了,结束。但是其中还是有些门道。接下来从前后端代码一起来看看文件下载这个功能。

正文

对于文件的下载,我们有几点需要注意,文件类型、文件是否跨域、文件数据返回形式

node环境搭建

npm install koa --save
npm install koa-router --save
npm i @koa/cors --save
npm install koa-static --save

创建目录

从前后端代码看文件下载方式

//app.js
let Koa = require('koa');
let app = new Koa();
let fs = require('fs')
let Router = require('koa-router')();

//静态web服务到public目录下找,返回资源链接
const path = require('path')
let koaStatic = require('koa-static');
app.use(koaStatic(path.join(__dirname, 'public')))

//跨域
const cors = require("@koa/cors")
app.use(cors())

Router.get('/', async (ctx) => {
  ctx.body = "ok"
})


app
  .use(Router.routes())   	//启动路由
  .use(Router.allowedMethods());
app.listen(3002);

nodemon app.js启动下服务器。ok,没有问题

从前后端代码看文件下载方式

文件有链接地址,动态创建a标签下载

有几点需要注意:

  1. 使用a标签下载,能下载浏览器不能直接预览的文件类型且名字是文件名字,如.doc、.xlsx、.zip等。而有些类型浏览器是可以预览的,使用a标签是直接打开预览

.txt、.html、.xml、.css、.js、.json、.jpg、.png、.gif、.bmp、.ico、.mp3、.mp4、.pdf

  1. 对于浏览器可预览的文件可以通过添加download属性下载,如download='名称.类型'。但是download只在同源(域名、协议、端口号一致)下有效

通用代码

  const downloadByUrl = (url: string, filename: string) => {
    if (!url) throw new Error('当前没有下载链接');
    const link = document.createElement("a");
    link.href = url;
    link.download = filename;
    document.body.append(link);
    link.click();
    document.body.removeChild(link);
  };

我们来分别对不可预览可预览同源可预览不同源,做一下测试 从前后端代码看文件下载方式

结果如下,跟我们上面说的一致。不可预览直接下载且名字是文件名字;同源可预览我们可以通过 download属性下载并设置名字,不同源可预览则是直接预览。

从前后端代码看文件下载方式

文件以流的形式

通过动态创建a标签下载

下载浏览器不可预览文件

Router.get('/download', (ctx) => {
  //设置名字,必要的。Content-disposition响应头用于控制用户代理对服务器返回的文件的处理方式
  ctx.set('Content-disposition', 'attachment;filename=' + '1.docx');
  let data = fs.readFileSync(path.join(__dirname, 'public', '1.docx'), (err, data) => {
    if (err) {
      return;
    }
  })
  ctx.body = data
})
  downloadByUrl('http://127.0.0.1:3002/download', '11.docx')

从前后端代码看文件下载方式

换成浏览器可浏览资源再看看

Router.get('/download', (ctx) => {
  //设置名字,必要的。Content-disposition响应头用于控制用户代理对服务器返回的文件的处理方式
  ctx.set('Content-disposition', 'attachment;filename=' + '2.jpg');
  let data = fs.readFileSync(path.join(__dirname, 'public', '2.jpg'), (err, data) => {
    if (err) {
      return;
    }
  })
  ctx.body = data
})
  downloadByUrl('http://127.0.0.1:3002/download', '22.jpg')

从前后端代码看文件下载方式

可以看到这种形式不管是浏览器可不可以浏览的文件都是可以下载的,但是名字不受我们的控制,而是受响应头Content-disposition控制的,一般有两种方式:

  • inline:直接在页面显示
  • attchment:以附件形式下载

filename表示下载的文件名

通过请求下载

跟上面的标签下载文件原理差不多,只是多了一步处理

发送请求

 axios({
          method: "get",
          url: "http://127.0.0.1:3002/download",
          //responseType 的作用用于告诉浏览器,如何解析服务端返回的数据
          responseType: 'blob'
        })
          .then((res: any) => {
            const link = document.createElement('a')
            //每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,
            //即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,
            //每个对象必须通过调用 URL.revokeObjectURL() 方法来释放
            const blobUrl =URL.createObjectURL(res.data)
            link.href = blobUrl
            link.download = '11.docx'
            document.body.appendChild(link)
            link.click();
            document.body.removeChild(link);
            //释放
            URL.revokeObjectURL(blobUrl);
          })

不管是什么资源都是可以下载的,而且名字是受我们控制的。

从前后端代码看文件下载方式

结语

感兴趣的去试试吧