1

Emberjs 通过 axios 下载文件

摘要: 目前项目中需要与后端合作,通过发送 GET 请求,后端返回文件流,前端进行文件的下载。

使用到的技术有:

  • Emberjs
  • axios

思路

接到这个需求的话,想着使用创建 a 链接,然后模拟点击 a 链接来完成下载,但是情况不是这样的。后端有多于一个的下载接口,首先是生成下载文件的接口, 这个接口主要是返回 需要下载的文件的name 以及相应的接口地址。而下载的文件可能不止一个,同时,对文件接口地址发送 GET 请求,会返回文件流,但是我们需要的是 CSV 格式的文件,所以想到通过 axios 来实现这个需求。

具体做法

既然方向确定了,那就是去做了。

在项目中安装插件/导入 axios

现在 Emberjs 封装好的 axios 插件 - ember-axios ,使用 ember install axios。这个插件没有文档,所以只能看源码,还好源码比较简单,就是简单的将 axios 的一些方法封装成一个 service 内的方法。

在项目文件中引入 axios

安装后在 Emberjs 项目中将此 service 引入近来

import { inject as service } from '@ember/service';

export default Controller.extend({
    // ...
    axios: service()
    // ...
});

这样即可使用这个插件中封装的一些 axios 的方法。

使用

之前也说过当前项目需要先发送一个请求,请求文件的接口地址。返回的值的格式为:

{
    "fileNames":[
        "filename=downloadFile1.csv",
        "filename=downloadFile2.csv"
    ],
    "status":"ok"
}

可以看到,如我们所想的那样,返回的并不一定是单个文件的地址,所以我们在接收到这个数据后:

import { isEmpty } from '@ember/utils';
import { all, reject } from 'rsvp';

//...
.then(data=> {
    if (data.status !== 'ok' || isEmpty(data.fileNames)) {
        return reject();
    }

    return all(data.fileNames.map(ele => {
        return axios.axios({
            url: `${ele}`,
            method: 'get',
            responseType: 'blob'
        });
    }));
});

在等待上面的请求发送成功之后,我们看看这段代码的意思。最上面的两个 import 是引入的一些 Emberjs 中封装的一些通用方法以及 promies 方法.在 then 之内的代码,先是验证是否返回成功。然后对数据进行遍历,并发送 axios 封装的 get请求。 其中axios.axios()ember-axios 封装的axios.create(this.config()) 源码地址 ,同时注意的是 config 对象中 responseType 填写的是 blob,这是保证文件能够下载成功的基础。
请求发送成功之后,我们需要对返回的数据进行处理,也就是:

.then(data => {
    data.forEach((res, index) => {
        const content = res.data,
            blob = new Blob([content], { type: 'text/csv' }),
            fileName = fileNames[index];

        if ('download' in document.createElement('a')) { // 非IE下载
            const elink = document.createElement('a');

            elink.download = fileName;
            elink.style.display = 'none';
            elink.href = URL.createObjectURL(blob);
            document.body.appendChild(elink);
            elink.click();
            URL.revokeObjectURL(elink.href); // 释放URL 对象
            document.body.removeChild(elink);
        } else { // IE10+下载
            navigator.msSaveBlob(blob, fileName);
        }
    });
}).catch(() => {
});

这段代码需要注意的是我们new Blob()接收的是 res.data 这个需要特别注意。另外就是此方法的第二个参数接收的 {type: 'text/csv'},因为次项目下载的是csv文件格式,其他的可以参考 MIME. 其他的就是创建一个 display:nonea标签,并触发点击事件。这时候浏览器就会进行下载。

总结

这算是在 Embjerjs 中进行下载流文件的一次船新尝试。

Write By Frank Wang

法研鲁迅
40 声望6 粉丝

引用和评论

0 条评论