前端下载文件常见的几种方式总结和下载插件impeldown的介绍和用法

书中仙
2019.06.23 15:09 字数 6226 阅读 60 评论 0 喜欢 1

前端下载文件通常有以下几种方式

方式一:链接,参数不多

 1. a标签,直接实现

// href 放下载地址; 
// download 为空,默认是下载地址上的文件名称,可以指定名称,如tp.csv,加download是避免json、img等文件直接在浏览器打开而不是下载;
// target="_blank"在新页面打开,避免当前页闪屏
<a href="" download="" target="_black">点击下载</a>

// 如需带参,直接在地址后加上url的search参数就可以,注意参数不要太多
<a class="download link-text" href="/newCrowd/crowdList/downFile?&is_tag=1&fileId=1023" target="_blank">点击下载</a>

2. window.open,location.href,借助js,点击按钮,调用方法实现

function downloadFile(url){
window.open(url);
}

function downloadFile(url){
location.href=url;
}

方式二:iframe

// js
function downloadFile(url){
var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
iframe.src =url;
}

// jq
function downloadFile(url){
$("body").append($("<iframe/>").attr("src",url);
}

方式三:form表单,参数较多

1. form表单,不带参

function downloadFile (){  
var url = "";
var form = $("<form></form>").attr({
action : url,
method : "post"
});
form.appendTo($("body")).submit();
form.remove();
}

2. form表单,带参,jq

    function downloadFile (data, url) {
// data格式
// obj {key: val}
// obj {key: [val]}
// obj {key: {key1: val}}

var dataHtml='';
for(var i in data){
var item=data[i];
var type=typeof item;
switch(type){
case 'object':
if($.isArray(item)){
for(var k=0,klen=item.length; k<klen; k++){
dataHtml+=createInput(i+'[]',item[k]); // name=key[] value=val
}
}else{
for(var k in item){
dataHtml+=createInput(i+'['+k+']',item[k]) // name=key[key1] value=val
}
}
break;
default:
dataHtml+=createInput(i,item);
}
}
var exportForm=$("#export_form");
if(!exportForm.length){
$('body').append('<form id="export_form" enctype="multipart/form-data" method="post" target="_blank" action="'+url+'">'+dataHtml+'</form>');
}else{
exportForm.html(dataHtml);
}
$("#export_form").submit();
$('#export_form').remove();
function createInput(name,data){
return '<input name="'+name+'" type="hidden" value="'+data+'">'
}
}

3. form 表单,带参,vue,element-ui

// 组件 download.vue
<template>
<div class="download">
<form :action="downloadUrl" method="post" target="_blank" style="display: none">
<template v-for="(value, key) in pageParams">
<!-- 值为数组或对象 -->
<template v-if="typeof value === 'object'">
<input type="hidden" v-if="value.length" v-for="item in value" :name="key+'[]'" :value="item">
<input type="hidden" v-else v-for="(childValue, childKey) in value" :name="key+'['+childKey+']'" :value="childValue">
</template>
<!-- 值为字符串或数字 -->
<input v-else type="hidden" :name="key" :value="value">
</template>
<button type="submit" ref="btnDownload"></button>
</form>
</div>
</template>
<script>
export default {
props: {
pageParams: {
type: Object,
default () {
return {}
}
},
downloadUrl: {
type: String,
required: true,
default: ''
}
},
methods: {
downLoad() {
this.$refs.btnDownload.click();
}
}
}
</script>
// 调用
<template>
<el-button @click="$refs.download.downLoad()" type="primary" size="small">下载</el-button>
<download :pageParams="params" :downloadUrl="api.downloadUrl" ref="download"></download>
</template>

<script>
import download from 'components/download/download';
export default {
data() {
return {
api: {
downloadUrl: `${this.urlBase}/adunit/download`
},
params: {}
}
},
components: {download}
}
</script>

方式四:前端组织内容,csv方式下载

前面三种方式都是通过前端请求路径实现下载,但有时需要前端直接组织内容下载。

    <a href="" download="文件.csv" id="btn">下载</a>
<a href="" download="中文文件.csv" id="btn_chinese">下载中文</a>
    var dataStr = "col1,col2,col3
hello,world,english";
var dataChineseStr = "姓名,年龄! 张三,34 王五,32 李四,25";

console.log()
// chrome
if (navigator.appName == "Netscape") {
var blob = new Blob([dataStr], {type: "text/csv,charset=utf-8"});
document.getElementById("btn").href = window.URL.createObjectURL(blob);

var blobChinese = new Blob(['ufeff'+dataChineseStr], {type: "text/csv,charset=utf-8"});
document.getElementById("btn_chinese").href = window.URL.createObjectURL(blobChinese);
} else {
document.getElementById("btn").href = "data:text/csv;charset=utf-8," + encodeURIComponent(dataStr);
document.getElementById("btn_chinese").href = "data:text/csv;charset=utf-8,ufeff" + encodeURIComponent(dataStr);
}

以上这几种方式基本是现在前端下载文件所能用到的,这几种方式各有优劣,但是他们有一个共同的缺点,就是无法监控下载进度,针对这一缺点我写了一个下载文件插件impeldown,原理是利用XmlHttpRequest2可以接收二进制文件的新特性,下面我给大家简单介绍一下

impeldown是什么?

一个浏览器端下载插件,可以监听下载进度,没有依赖任何第三方框架,压缩后大小仅4kb,小巧方便,使用灵活

演示地址

http://demo.taohuayuanskill.com/#/impeldown

使用注意

  • 受到浏览器同源策略的限制,impeldown无法下载跨域资源,只能下载本域资源或者服务端开启CORS
  • 服务端返回的Response Headers必须包含Content-Length,否则无法监听到下载进度,但是可以正常下载

安装

npm 的方式
npm install impeldown --save

cnpm insatll impeldown --save

支持CDN引入
git地址:https://github.com/cttaohua/impeldown
引入dist文件夹下的impeldown.min.js
<script src="./dist/impeldown.js"></script>

使用

在js中添加

import impeldown from 'impeldown'

可以简单的传入一个链接

new impeldown('https://taohuayuanskill.com/uploadImg/cover/97526.png') // 示例下载url

或者选择传入一个对象来监听下载进度

new impeldown({
url: 'https://taohuayuanskill.com/uploadImg/cover/97526.png', // 必填项
name: '下载.png', // 非必填项
onStart: function() { // 开始下载
console.log('开始下载啦')
},
onProgress: function(p) { // 监听进度
console.log('现在下载了'+p)
},
onAbort: function() { // 被用户中止下载
console.log('您取消了下载')
},
onError: function() { // 传输中出现错误
console.log('出错了')
},
onSuccess: function() { // 下载成功
console.log('下载成功')
},
onComplete: function() { // 下载结束(成功失败都会调用)
console.log('下载结束啦')
}
})

注意事项

如果没有定义name的话,impeldown会自动默认下载的文件名为静态资源的文件名,但是如果下载路径不是静态资源,而是动态生成的文件的话,impeldown会设置文件名为8位的随机字符串加文件后缀名。

npm包名:impeldown

github地址

欢迎大家来点小星星


支付二维码
登录 后发表评论
${comment_count}条评论 评论

智慧如你,不想发表一点想法咩~

推荐阅读
更多精彩内容