文件下载方法汇总

20210329

文件下载方法汇总

1、单文件下载

1.1 方法一:window.open

适用范围:
  • 1、已经有了文件在服务器上的存储地址
  • 2、文件类型不是图片也不是pdf,也不是.mp3等可以直接被浏览器以预览形式打开的文件类型。
  • 3、需要打开一个新的tab页
代码:

这个重点其实不在前端方法,而在于文件服务器的配置。

以nginx为例

// nginx.conf

http {
    // ... 一些默认配置,安装nginx就帮你写好的不用管
    
    server {
        listen 8080;
        server_name citybrain;
        
        location /fileDownload {
            add_header Content-Disposition: 'attachment';
            add_header  Content-Type application/octet-stream;
            root /data/file/;
        }
    }
    
}
// 注意这里要用 window.open
const url = 'http://localhost:8080/fileDownload/example.zip';
window.open(url);

不要使用window.location.href = url;下载。
会有两个问题:

  • 1、会被项目中的路由router相关的js代码拦截到
  • 2、即便router给放过去了,也成功下载了,用户要查看原来的页面还有做后退操作,太麻烦了。

1.2 方法二:二进制流转化

适用范围:
  • 1、文件通过接口二进制流的形式返回
  • 2、有明确的文件类型
  • 3、不需要打开一个新的tab页
代码:
// blob.js  axios配置
import axios from 'axios';

const blob = axios .create({
	baseURL: process.env.VUE APP_ BASE_ API, // url = base url + request url
	withCredentials: true, // send cookies when cross - domain requests 
	timeout:60000, //request timeout
	responseType: ' blob'
});

blob.interceptors.request.use(
	config => config ,
	error => {
		// do something with request error
		console. log(error)。// for debug
		return Promise.reject(error)
	}
)

blob.interceptors.response.use(
	response => {
		const res = response.data;
		if (res) {
			return res;
		} else {
			Message.error({
				content: ' 数据接口异常,请联系管理员! ',
				duration: 5,
				return Promise. reject(new Error(' Error'));
			});
		}
	},
	error => {
		console.log('err' + error). // for debug
		Message.error({
			content: '数据接口异常,请联系管理员!',
			duration: 5
		})
		return Promise.reject(error);
	}
)
export default blob;
// 获取二进制流的接口
export function downloadExcel(params) {
    return blob({
        url: '',
        method: 'post',
        data: Qs.stringify(param)
    })
}

// 将二进制流转换为文件
downloadExcel(param).then((res) => {
    if (!res) return;
    
    let title = '文件名称.excel';
    downloadFile(res, title, 'application/vnd.ms-excel;charset=UTF-8');
});

function downloadFile(data, title, type) {
    let blob = new Blob([res], {
        type: type
    });
    if (navigator.msSaveOrOpenBlob) {
        navigator.msSaveOrOpenBlob(blob, title);
    } else {
        let url = window.URL.createobjectURL(
        	blob
        );
        let link = document.createElement('a');
        link.style.display = 'none';
        link.href = url;
        link.download = title;
        document.body.appendchild(link);
        link.click();        
    }
}

1.3 方法三:url下载

本质上是1.1和1.2方法的综合.

适用范围:
  • 1、已经有了文件在服务器上的存储地址
  • 2、文件类型不是图片也不是pdf,也不是.mp3等可以直接被浏览器以预览形式打开的文件类型。
  • 3、不需要打开一个新的tab页
  • 4、文件不能跨域
代码:
/**
* @description 根据url下载而不是预览(这种写法会有跨域问题)
* @param {*} url
* @param {*} callback回调方法
* @param {*} options { responseType: 'blob', name: ' 文件名.suffix'}
*/
export function fileAjax(url, callback, options) {
    let xhr = new XMLHttpRequest();
    xhr.open(' get', url, true);
    if (options .responseType) {
        xhr.responseType = options.responseType;
    }
    xhr.onreadystatechange = function() {
    if (xhr.readystate === 4 && xhr.status === 200) {
        downloadFile(xhr.response, options.name);
        if (callback && typeof callback === ' function') {
            callback(xhr);
        }
    }
    xhr.send();
}

function downloadFile(content, filename) k
    window.URL = window.URL || window.webkitURL;
    let a = document. createElement( 'a' );
    let blob = new Blob([content]);
    //通过二进制文件创建url
    let url = window.URL.createobjectURL(blob); 
    a.href = url;
    a. download = filename ;
    a.click( );
    //销毁创建的url
    window.URL.revoke0bjectURL (url);
}

TIPS:可能会遇到的问题

1、pdf, 图片等,使用window.open方法会被浏览器认为是预览而不是下载.

解决方法:

export function downloadByUrl(url, fileName) {
    let dom_a = document.createElement('a');
    dom_a.href = url;
    dom_a.download = filename; // 控制仅下载不预览的重要属性
    dom_a.click();
    
    //销毁生成的dom
    dom_a.remove();
}

不过,很奇怪的事,上面这个方法在chrome中总是时好时坏。

2、多文件/批量下载

实现多文件下载,本质上是将多文件转化为单文件下载。

有两种思路:

  • 1、后端将多个文件整合成一个压缩包文件.zip,然后给前端下载
  • 2、前端多次调用单文件下载接口,由前端将获取的二进制流合成一个压缩包.

2.1 window.open

后端将多个文件整合成一个压缩包文件.zip,然后给前端下载

适用范围:
  • 1、已经有了文件在服务器上的存储地址
  • 2、文件类型不是图片也不是pdf,也不是.mp3等可以直接被浏览器以预览形式打开的文件类型。
  • 3、需要打开一个新的tab页
代码:
window.open(url);

2.2 二进制流转化

后端将多个文件整合成一个压缩包文件.zip,然后给前端下载

实际上和1.2的二进制流转化是一模一样的,只不过最后下载的结果是一个包含多个文件的压缩包.zip文件

适用范围:
  • 1、文件通过接口二进制流的形式返回
  • 2、有明确的文件类型
  • 3、不需要打开一个新的tab页
代码
// 接口中获取二进制流
// ...省略

// 将二进制流转换为文件
downloadExcel(param).then((res) => {
    if (!res) return;
    
    let title = '文件名称.zip';
    downloadFile(res, title, 'application/zip');
});

function downloadFile(data, title, type) {
    let blob = new Blob([res], {
        type: type
    });
    if (navigator.msSaveOrOpenBlob) {
        navigator.msSaveOrOpenBlob(blob, title);
    } else {
        let url = window.URL.createobjectURL(
        	blob
        );
        let link = document.createElement('a');
        link.style.display = 'none';
        link.href = url;
        link.download = title;
        document.body.appendchild(link);
        link.click();        
    }
}

2.3 使用jszip插件

前端多次调用单文件下载接口,由前端将获取的二进制流合成一个压缩包.
https://stuk.github.io/jszip/

适用范围

1、能够将多文件下载转化成多个单文件下载

比如,你已经有了多个下载单文件的url

npm install file-saver jszip -S
代码:
import { saveAs } from 'file-saver';
let JSZIP = require('jszip');


// for 循环调用接口 获取二进制流
let blobList = [...];

// 调用jszip方法进行压缩
function compressZip(zipName, blobList) {
    let jsZip = new JSZIP();
    blobList.forEach((item, index) => {
        jsZip .file(`文件名${index}.png`, item)
    });
    jsZip.generateAsync({type:"blob"})
    .then(function(content) {
        // see FileSaver.js
        saveAs(content, zipName);
    });
}

实际上我是使用失败了的。不知道是什么问题.如果下次还有机会使用的话可以看官网文档尝试一下.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值