likes
comments
collection
share

前端文件下载(一)

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

本文,我们将通过案例,讲解如何进行超链接文件下载。

假设我们返回了一个文件的超链接,比如 http://localhost:3000/test.txt,我们可以怎么下载呢?

演示环境(Main)

Google Chrome: 版本 116.0.5845.187(正式版本) (arm64)

Node: v14.18.1

Vscode:插件 - Live Server

同源

我们先来了解下同源的情况下下载超链接文件

我们通过 koa 开启一个 SSR 的应用:

const Koa = require('koa');
const Router = require('koa-router');
const ejs = require('ejs');
const fs = require('fs');
const path = require('path');
const static = require('koa-static');

const app = new Koa();
const router = new Router();

// static file
const staticPath = path.join(__dirname, 'public');
app.use(static(staticPath));

// template
const template = fs.readFileSync('template.ejs', 'utf-8');

router.get('/', async (ctx) => {

  const fileName = 'test.txt';
  const fileUrl = path.join(fileName);

  // simulated data
  const templateData = {
    title: 'SSR Page',
    content: 'Hello, Jimmy!',
    fileUrl: fileUrl
  };

  const html = await ejs.render(template, templateData);
  // return
  ctx.body = html;
});

app.use(router.routes());

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

上面我们开启了一个服务,将文件数据提供给 ejs 模版文件。

HTMLa 标签

添加模版文件内容:

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
  </head>
  <body>
    <h1 id="app"><%= content %></h1>
    <a href="<%= fileUrl %>" download="file.txt">Download File: <%= fileUrl %></a>
  </body>
</html>

运行服务后,整个页面渲染如下:

前端文件下载(一)

我们触发下载:

前端文件下载(一)

是的,原先的文件名是 text.txt,我们在设定 <a> 标签的时候,使用 download 属性,浏览器会自动下载文件,且我们更改了下载的名称(给 download 设定了值为 file.txt)。当然,我们不指定 download 属性值,则会以默认的文件名保存文件,如下:

前端文件下载(一)

通过 JS 构建 a 标签

我们更改下 ejs 模版文件的内容:

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
  </head>
  <body>
    <h1 id="app"><%= content %></h1>
    <button id="download">Download File: <%= fileUrl %></button>
    <script>
      (function(){
        let downloadBtn = document.getElementById('download');
        downloadBtn.addEventListener('click', function() {
          const link = document.createElement('a'); // create
          link.href = '<%= fileUrl %>';
          link.setAttribute('download', 'file');
          document.body.appendChild(link); // append
          link.click(); // click
          document.body.removeChild(link); // remove 
        })
      })()
    </script>
  </body>
</html>

点击下载按钮,会通过 javascript 创建一个 a 标签,然后设定其 url 链接和 download 属性值改变下载文件名。如果你不想更改下载的文件名,可以设置设置为 link.setAttribute('download', '') 即可。

前端文件下载(一)

跨域

那么,上面说到的同源中的两种方法,是否可以在跨域中使用到呢?我们来尝试下:

我们使用 Koa 开启一个服务,有返回文件超链接的接口:

const Koa = require('koa');
const Router = require('koa-router');
const fs = require('fs');
const path = require('path');
const static = require('koa-static');

const app = new Koa();
const router = new Router();

// static file
const staticPath = path.join(__dirname, 'public');
app.use(static(staticPath));

router.get('/', async (ctx) => {

  const fileName = 'test.txt';
  const fileUrl = path.join(fileName);

  // simulated data
  const data = {
    title: 'Hello, Jimmy!',
    fileUrl: fileUrl
  };
  // return
  ctx.body = {
    data
  };
});

app.use(router.routes());

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

启动服务,我们访问 http://localhost:3000/test.txt,则会看到返回信息:

前端文件下载(一)

为了方便看到自动吊起浏览器的下载,我们更改下文件为:

// const fileName = 'test.txt'; // -
const fileName = 'test.txt.zip'; // +

HTMLa 标签

我们另起项目,添加下 html 文件:

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Download Client</title>
</head>
<body>
  <a href="http://localhost:3000/test.txt.zip">Download File</a>
</body>
</html>

开启服务,在端口号 5500 上监听。点击上面的 a 标签,那么就可以自动跳转下载该文件。那么,我们要更改下载的文件名称,可以?

我们来添加 download 属性值为 download='custom',发现并不能更改文件名:

前端文件下载(一)

通过 JS 构建 a 标签

这个方法也能实现文件的下载,因为都是通过控制 a 标签。那么,它能不能改变文件名呢?是不能的

我们更改下 html 文件:

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Download Client</title>
</head>
<body>
  <button id="download">Download File</button>
  <script>
    (function(){
      let downloadBtn = document.getElementById('download');
      downloadBtn.addEventListener('click', function() {
        const link = document.createElement('a'); // create
        link.href = 'http://localhost:3000/test.txt.zip';
        link.setAttribute('download', 'custom');
        document.body.appendChild(link); // append
        link.click(); // click
        document.body.removeChild(link); // remove 
      })
    })()
  </script>
</body>
</html>

我们设定了自定义的文件名 link.setAttribute('download', 'custom');,但是没有效果。如下:

前端文件下载(一)

总结

本文主要是通过介绍 a 标签的方法来下载超链接文件,介绍了用单纯的 htmljavascript 的方法来操作。两者的效果都是一样。最后,我们得出的结果如下:

  • 同源和跨域下,都可以使用 a 标签对超链接文件进行预览或者下载
  • 同源下,超链接文件可以通过 a 标签 download 属性值更改下载文件的名称;跨域下,超链接文件不能被更改文件名称
  • 超链接文件,通过a 标签,调用起浏览器默认的下载,可以在自带的浏览器上看到下载的进度。页面上监听不到下载的进度。

读者对 超链接文件 下载有什么见解,可以评论区留言,大家一起成长~