JS端基于download.js实现图片、视频时直接下载而不是打开预览


Posted in Javascript onMay 09, 2020

项目中的附件列表,通常情况都需要提供下载、删除的功能,功能本身没有什么要说的,都是基本功能,使用浏览器的的下载功能,也都是用window.open(url),或者window.location.href=url的方式,url即为附件下载接口,浏览器自动解析,如果是图片、视频、txt等格式的会直接预览文件,而不是像docx、xlsx一样直接下载,项目中为了功能明确,将预览单独加了一个查看按钮,下载按钮要实现无论什么文件格式都直接下载。

JS端基于download.js实现图片、视频时直接下载而不是打开预览

有两种方式处理:

一.后台接口层面处理:(比较常见)

响应头中添加标识:
Response.AddHeader("Content-Disposition", "attachment; filename=" +
HttpUtility.UrlEncode(annotation.FileName, System.Text.Encoding.UTF8));

JS端基于download.js实现图片、视频时直接下载而不是打开预览

添加后,浏览器就会全都直接下载,不区分文件格式

二.前端JS使用XMLHttpRequest结合download.js处理

1)首先页面中需要引用download.js

download官方:http://danml.com/download.html

http://danml.com/js/download2.js

2)公共方法

/*
    * 使用download.js 强制浏览器下载图片、视频等文件
    * @param {any} url url链接地址
    * @param {any} strFileName 文件名
    * @param {any} strMimeType 文件类型
    * dzl
    * 2020年5月8日
     */
    function downloadfile(url, strFileName, strMimeType) {
      var xmlHttp = null;
      if (window.ActiveXObject) {
        // IE6, IE5 浏览器执行代码
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
      } else if (window.XMLHttpRequest) {
        // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
        xmlHttp = new XMLHttpRequest();
      }
      //2.如果实例化成功,就调用open()方法:
      if (xmlHttp != null) {
        xmlHttp.open("get", url, true);
        xmlHttp.responseType = 'blob';//关键
        xmlHttp.send();
        xmlHttp.onreadystatechange = doResult; //设置回调函数
      }
      function doResult() {
        if (xmlHttp.readyState == 4) { //4表示执行完成
          if (xmlHttp.status == 200) { //200表示执行成功
            download(xmlHttp.response, strFileName, strMimeType);
          }
        }
      }
    }

注意: xmlHttp.responseType = 'blob';是关键,必须要设置

3)下载按钮点击事件中调用公共方法

downloadfile(url, filename, getFileType(filename))

附上根据文件名的尾缀 返回文件类型的公共方法:

/*
 * 根据文件名的尾缀 返回文件类型
 * @param {any} fileName 文件名
 * dzl
 * 2020年5月9日
 */
function getFileType(fileName) {
  // 后缀获取
  let suffix = '';
  // 获取类型结果
  let result = '';
  try {
    const flieArr = fileName.split('.');
    suffix = flieArr[flieArr.length - 1];
  } catch (err) {
    suffix = '';
  }
  // fileName无后缀返回 false
  if (!suffix) { return false; }
  suffix = suffix.toLocaleLowerCase();
  // 图片格式
  const imglist = ['png', 'jpg', 'jpeg', 'bmp', 'gif'];
  // 进行图片匹配
  result = imglist.find(item => item === suffix);
  if (result) {
    return 'image';
  }
  // 匹配txt
  const txtlist = ['txt'];
  result = txtlist.find(item => item === suffix);
  if (result) {
    return 'txt';
  }
  // 匹配 excel
  const excelist = ['xls', 'xlsx'];
  result = excelist.find(item => item === suffix);
  if (result) {
    return 'excel';
  }
  // 匹配 word
  const wordlist = ['doc', 'docx'];
  result = wordlist.find(item => item === suffix);
  if (result) {
    return 'word';
  }
  // 匹配 pdf
  const pdflist = ['pdf'];
  result = pdflist.find(item => item === suffix);
  if (result) {
    return 'pdf';
  }
  // 匹配 ppt
  const pptlist = ['ppt', 'pptx'];
  result = pptlist.find(item => item === suffix);
  if (result) {
    return 'ppt';
  }
  // 匹配 视频
  const videolist = ['mp4', 'm2v', 'mkv', 'rmvb', 'wmv', 'avi', 'flv', 'mov', 'm4v'];
  result = videolist.find(item => item === suffix);
  if (result) {
    return 'video';
  }
  // 匹配 音频
  const radiolist = ['mp3', 'wav', 'wmv'];
  result = radiolist.find(item => item === suffix);
  if (result) {
    return 'radio';
  }
  // 其他 文件类型
  return 'other';
}

download.js源码

//download.js v4.21, by dandavis; 2008-2018. [MIT] see http://danml.com/download.html for tests/usage
// v1 landed a FF+Chrome compatible way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling.
// v4 adds AMD/UMD, commonJS, and plain browser support
// v4.1 adds url download capability via solo URL argument (same domain/CORS only)
// v4.2 adds semantic variable names, long (over 2MB) dataURL support, and hidden by default temp anchors
// https://github.com/rndme/download

(function (root, factory) {
	if (typeof define === 'function' && define.amd) {
		// AMD. Register as an anonymous module.
		define([], factory);
	} else if (typeof exports === 'object') {
		// Node. Does not work with strict CommonJS, but
		// only CommonJS-like environments that support module.exports,
		// like Node.
		module.exports = factory();
	} else {
		// Browser globals (root is window)
		root.download = factory();
 }
}(this, function () {

	return function download(data, strFileName, strMimeType) {

		var self = window, // this script is only for browsers anyway...
			defaultMime = "application/octet-stream", // this default mime also triggers iframe downloads
			mimeType = strMimeType || defaultMime,
			payload = data,
			url = !strFileName && !strMimeType && payload,
			anchor = document.createElement("a"),
			toString = function(a){return String(a);},
			myBlob = (self.Blob || self.MozBlob || self.WebKitBlob || toString),
			fileName = strFileName || "download",
			blob,
			reader;
			myBlob= myBlob.call ? myBlob.bind(self) : Blob ;
	 
		if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
			payload=[payload, mimeType];
			mimeType=payload[0];
			payload=payload[1];
		}


		if(url && url.length< 2048){ // if no filename and no mime, assume a url was passed as the only argument
			fileName = url.split("/").pop().split("?")[0];
			anchor.href = url; // assign href prop to temp anchor
		 	if(anchor.href.indexOf(url) !== -1){ // if the browser determines that it's a potentially valid url path:
    		var ajax=new XMLHttpRequest();
    		ajax.open( "GET", url, true);
    		ajax.responseType = 'blob';
    		ajax.onload= function(e){ 
				 download(e.target.response, fileName, defaultMime);
				};
    		setTimeout(function(){ ajax.send();}, 0); // allows setting custom ajax headers using the return:
			  return ajax;
			} // end if valid url?
		} // end if url?


		//go ahead and download dataURLs right away
		if(/^data:([\w+-]+\/[\w+.-]+)?[,;]/.test(payload)){
		
			if(payload.length > (1024*1024*1.999) && myBlob !== toString ){
				payload=dataUrlToBlob(payload);
				mimeType=payload.type || defaultMime;
			}else{			
				return navigator.msSaveBlob ? // IE10 can't do a[download], only Blobs:
					navigator.msSaveBlob(dataUrlToBlob(payload), fileName) :
					saver(payload) ; // everyone else can save dataURLs un-processed
			}
			
		}else{//not data url, is it a string with special needs?
			if(/([\x80-\xff])/.test(payload)){			 
				var i=0, tempUiArr= new Uint8Array(payload.length), mx=tempUiArr.length;
				for(i;i<mx;++i) tempUiArr[i]= payload.charCodeAt(i);
			 	payload=new myBlob([tempUiArr], {type: mimeType});
			}		 
		}
		blob = payload instanceof myBlob ?
			payload :
			new myBlob([payload], {type: mimeType}) ;


		function dataUrlToBlob(strUrl) {
			var parts= strUrl.split(/[:;,]/),
			type= parts[1],
			indexDecoder = strUrl.indexOf("charset")>0 ? 3: 2,
			decoder= parts[indexDecoder] == "base64" ? atob : decodeURIComponent,
			binData= decoder( parts.pop() ),
			mx= binData.length,
			i= 0,
			uiArr= new Uint8Array(mx);

			for(i;i<mx;++i) uiArr[i]= binData.charCodeAt(i);

			return new myBlob([uiArr], {type: type});
		 }

		function saver(url, winMode){

			if ('download' in anchor) { //html5 A[download]
				anchor.href = url;
				anchor.setAttribute("download", fileName);
				anchor.className = "download-js-link";
				anchor.innerHTML = "downloading...";
				anchor.style.display = "none";
 				anchor.addEventListener('click', function(e) {
 					e.stopPropagation();
 					this.removeEventListener('click', arguments.callee);
 				});
				document.body.appendChild(anchor);
				setTimeout(function() {
					anchor.click();
					document.body.removeChild(anchor);
					if(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(anchor.href);}, 250 );}
				}, 66);
				return true;
			}

			// handle non-a[download] safari as best we can:
			if(/(Version)\/(\d+)\.(\d+)(?:\.(\d+))?.*Safari\//.test(navigator.userAgent)) {
				if(/^data:/.test(url))	url="data:"+url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
				if(!window.open(url)){ // popup blocked, offer direct download:
					if(confirm("Displaying New Document\n\nUse Save As... to download, then click back to return to this page.")){ location.href=url; }
				}
				return true;
			}

			//do iframe dataURL download (old ch+FF):
			var f = document.createElement("iframe");
			document.body.appendChild(f);

			if(!winMode && /^data:/.test(url)){ // force a mime that will download:
				url="data:"+url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
			}
			f.src=url;
			setTimeout(function(){ document.body.removeChild(f); }, 333);

		}//end saver




		if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)
			return navigator.msSaveBlob(blob, fileName);
		}

		if(self.URL){ // simple fast and modern way using Blob and URL:
			saver(self.URL.createObjectURL(blob), true);
		}else{
			// handle non-Blob()+non-URL browsers:
			if(typeof blob === "string" || blob.constructor===toString ){
				try{
					return saver( "data:" + mimeType  + ";base64," + self.btoa(blob) );
				}catch(y){
					return saver( "data:" + mimeType  + "," + encodeURIComponent(blob) );
				}
			}

			// Blob but not URL support:
			reader=new FileReader();
			reader.onload=function(e){
				saver(this.result);
			};
			reader.readAsDataURL(blob);
		}
		return true;
	}; /* end download() */
}));

js文件下载插件介绍和使用方法 download.js

在前端想要生成txt或者其他格式文件来保存一些数据,或者在数据请求服务器成功后想要将数据生成文件并下载,这些需求还是比较多的,这里使用到的download.js。既可以满足这些需求。

第一步:下载
1.下载可以在官网上进行下载 原网址:download2.js
2.也可以使用我上传的资源(下载与上述官网) 免费哦! 下载

第二步:引用
1.将下载的文件放在项目中,并使用 <script src="./download2.js"></script> 进行引用 (速度快)
2.使用网络引用 <script src="http://danml.com/js/download2.js"></script>

第三步:开始使用

//生成一个txt的文件,讲字符串变量 str 的内容放在里面,并完成下载
var str = "hello world可以中文吗?答案:可以的";
download(str, "Text.txt", "text/plain");

//也将生成一个txt文件,和上面的结果是一摸一样
str = "data:text/plain,hello%20world";
download(str, "dlDataUrlText.txt", "text/plain");

//将数组或者json对象写入到文件中
var debug = {hello : "world"};
var blob = new Blob([JSON.stringify(debug, null, 2)]);
download(blob, "dlTextBlob.txt", "text/plain");

var str= "hello world", arr= new Uint8Array(str.length);
str.split("").forEach(function(a,b){
  arr[b]=a.charCodeAt();
});
download( arr, "textUInt8Array.txt", "text/plain" );

//将html页面中的一部分生成单独的 html文档
download(document.body.outerHTML, "dlHTML.html", "text/html");

//给字符串添加标签,或者html片段直接给方法,将会生成对应内容的文件
download(new Blob(["hello world".bold()]), "dlHtmlBlob.html", "text/html");

 //将ajax查询回来的结果,赋值给文件,并下载
$.ajax({
  url: "/download.html",
  success: download.bind(true, "text/html", "dlAjaxCallback.html")
});

//将图片的base64装入到图片中并下载。
download("data:image/gif;base64,R0lGODlhRgAVAIcAAOfn5+/v7/f39////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yH5BAAAAP8ALAAAAABGABUAAAj/AAEIHAgggMGDCAkSRMgwgEKBDRM+LBjRoEKDAjJq1GhxIMaNGzt6DAAypMORJTmeLKhxgMuXKiGSzPgSZsaVMwXUdBmTYsudKjHuBCoAIc2hMBnqRMqz6MGjTJ0KZcrz5EyqA276xJrVKlSkWqdGLQpxKVWyW8+iJcl1LVu1XttafTs2Lla3ZqNavAo37dm9X4eGFQtWKt+6T+8aDkxUqWKjeQUvfvw0MtHJcCtTJiwZsmLMiD9uplvY82jLNW9qzsy58WrWpDu/Lp0YNmPXrVMvRm3T6GneSX3bBt5VeOjDemfLFv1XOW7kncvKdZi7t/S7e2M3LkscLcvH3LF7HwSuVeZtjuPPe2d+GefPrD1RpnS6MGdJkebn4/+oMSAAOw==", "dlDataUrlBin.gif", "image/gif");

//使用xhr获取本域名下文件,并封装到文件进行下载。这里的前提是xhr访问的文件必须和该程序执行在同一域名下,
//否则会报跨域的问题。比如此程序执行在localhost下面,而这里的访问地址使用的是http://danml.com,就会访问不成功。
  var x=new XMLHttpRequest();
  x.open("GET", "http://danml.com/wave2.gif", true);
  x.responseType = 'blob';
  x.οnlοad=function(e){
    download(x.response, "dlBinAjax.gif", "image/gif" );
  };
  x.send();

扩展:还可以使用文件上传再下载进行测试。

<input id="file" type="file" οnchange="download(this.files[0], this.files[0].name, this.files[0].type)">

以上就是JS端基于download.js实现图片、视频时直接下载而不是打开预览的详细内容,更多关于js实现图片、视频时直接下载的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
jquery对表单操作2
Apr 06 Javascript
js触发select onchange事件的小技巧
Aug 05 Javascript
基于Bootstrap实现图片轮播效果
May 22 Javascript
JS获取和修改元素样式的实例代码
Aug 06 Javascript
js判断radiobuttonlist的选中值显示/隐藏其它模块的实现方法
Aug 25 Javascript
Angular2 路由问题修复详解
Mar 01 Javascript
微信小程序 本地数据读取实例
Apr 27 Javascript
jQuery自定义元素右键点击事件(实现案例)
Apr 28 jQuery
vue2组件之select2调用的示例代码
Oct 12 Javascript
基于js原生和ajax的get和post方法以及jsonp的原生写法实例
Oct 16 Javascript
从0到1搭建element后台框架优化篇(打包优化)
May 12 Javascript
jquery实现穿梭框功能
Jan 19 jQuery
JS 获取文件后缀,判断文件类型(比如是否为图片格式)
May 09 #Javascript
js根据后缀判断文件文件类型的代码
May 09 #Javascript
Element实现表格嵌套、多个表格共用一个表头的方法
May 09 #Javascript
JS原形与原型链深入详解
May 09 #Javascript
JavaScript中的this妙用实例分析
May 09 #Javascript
JavaScript中继承原理与用法实例入门
May 09 #Javascript
jQuery三组基本动画与自定义动画操作实例总结
May 09 #jQuery
You might like
菜鸟修复电子管记
2021/03/02 无线电
PHP伪造referer实例代码
2008/09/20 PHP
php SQL之where语句生成器
2009/03/24 PHP
php中base_convert()进制数字转换函数实例
2014/11/20 PHP
用php来限制每个ip每天浏览页面数量的实现思路
2015/02/24 PHP
在WordPress中安装使用视频播放器插件Hana Flv Player
2016/01/04 PHP
PHP批量去除BOM头内容信息代码
2016/03/11 PHP
PHP文件下载实例代码浅析
2016/08/17 PHP
js类中的公有变量和私有变量
2008/07/24 Javascript
TreeView 用法(有代码)(asp.net)
2011/07/15 Javascript
php图像生成函数之间的区别分析
2012/12/06 Javascript
推荐一个封装好的getElementsByClassName方法
2014/12/02 Javascript
AngularJS入门教程(二):AngularJS模板
2014/12/06 Javascript
javascript实现依次输入input自动定焦
2014/12/23 Javascript
jQuery特殊符号转义的实现
2016/11/30 Javascript
Javascript this 函数深入详解
2016/12/13 Javascript
vuejs2.0实现分页组件使用$emit进行事件监听数据传递的方法
2017/02/22 Javascript
微信小程序获取音频时长与实时获取播放进度问题
2018/08/28 Javascript
关于NodeJS中的循环引用详解
2019/07/23 NodeJs
element-ui 文件上传修改文件名的方法示例
2019/11/05 Javascript
微信小程序自定义tabBar的踩坑实践记录
2020/11/06 Javascript
[59:32]Liquid vs Fnatic 2019国际邀请赛淘汰赛败者组BO1 8.20.mp4
2020/07/19 DOTA
pycharm 主题theme设置调整仿sublime的方法
2018/05/23 Python
Python批量查询关键词微信指数实例方法
2019/06/27 Python
Python使用Numpy模块读取文件并绘制图片
2020/05/13 Python
python复合条件下的字典排序
2020/12/18 Python
HTML5 Canvas概述
2009/08/26 HTML / CSS
童装店创业计划书
2014/01/09 职场文书
村当支部个人对照检查材料思想汇报
2014/10/06 职场文书
秦始皇兵马俑导游词
2015/02/02 职场文书
齐云山导游词
2015/02/06 职场文书
html5实现点击弹出图片功能
2021/07/16 HTML / CSS
JavaScript设计模式之原型模式详情
2022/06/21 Javascript
mysql全面解析json/数组
2022/07/07 MySQL
Nginx如何限制IP访问只允许特定域名访问
2022/07/23 Servers
Python中tqdm的使用和例子
2022/09/23 Python