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插件之自动添加删除行功能介绍
Oct 14 Javascript
js/jquery解析json和数组格式的方法详解
Jan 09 Javascript
javascript从image转换为base64位编码的String
Jul 29 Javascript
jQuery中outerHeight()方法用法实例
Jan 19 Javascript
jQuery拖拽排序插件制作拖拽排序效果(附源码下载)
Feb 23 Javascript
javaScript数组迭代方法详解
Apr 14 Javascript
javascript回到顶部特效
Jul 30 Javascript
AngularJS应用开发思维之依赖注入3
Aug 19 Javascript
js 能实现监听F5页面刷新子iframe 而父页面不刷新的方法
Nov 09 Javascript
Webpack中css-loader和less-loader的使用教程
Apr 27 Javascript
JavaScript HTML DOM元素 节点操作汇总
Jul 29 Javascript
vue实现element表格里表头信息提示功能(推荐)
Nov 20 Javascript
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
PHP 线程安全与非线程安全版本的区别深入解析
2013/08/06 PHP
php中Snoopy类用法实例
2015/06/19 PHP
PHP用FTP类上传文件视频等的简单实现方法
2016/09/23 PHP
浅谈PHP表单提交(POST&amp;GET&amp;URL编/解码)
2017/04/03 PHP
PHP+redis实现的悲观锁机制示例
2018/06/12 PHP
PHP设计模式之模板方法模式实例浅析
2018/12/20 PHP
tp5.0框架隐藏index.php入口文件及模块和控制器的方法分析
2020/02/11 PHP
PHP常用字符串函数用法实例总结
2020/06/04 PHP
对联广告js flash激活
2006/10/19 Javascript
javascript 面向对象全新理练之原型继承
2009/12/03 Javascript
从零开始学习jQuery (六) jquery中的AJAX使用
2011/02/23 Javascript
JavaScript中数组的排序、乱序和搜索实现代码
2011/11/30 Javascript
js Array操作的最简短最容易理解方法
2013/12/09 Javascript
Node.js程序中的本地文件操作用法小结
2016/03/06 Javascript
浏览器兼容的JS写法总结
2016/04/27 Javascript
jQuery简单注册和禁用全局事件的方法
2016/07/25 Javascript
jQuery实现下拉菜单的实例代码
2017/06/19 jQuery
基于匀速运动的实例讲解(侧边栏,淡入淡出)
2017/10/17 Javascript
详解vue-meta如何让你更优雅的管理头部标签
2018/01/18 Javascript
JavaScript实现省份城市的三级联动
2020/02/11 Javascript
基于vue.js仿淘宝收货地址并设置默认地址的案例分析
2020/08/20 Javascript
Python实现的生成格雷码功能示例
2018/01/24 Python
numpy concatenate数组拼接方法示例介绍
2019/05/27 Python
python+selenium 点击单选框-radio的实现方法
2019/09/03 Python
opencv python Canny边缘提取实现过程解析
2020/02/03 Python
python图形开发GUI库wxpython使用方法详解
2020/02/14 Python
推荐10个CSS3 制作的创意下拉菜单效果
2014/02/11 HTML / CSS
英国家居用品和家居装饰品购物网站:Cox & Cox
2019/08/25 全球购物
Ray-Ban雷朋奥地利官网:全球领先的太阳眼镜品牌
2020/10/12 全球购物
美国知名眼镜网站:Target Optical
2020/04/04 全球购物
三年级语文教学反思
2014/02/01 职场文书
计算机网络及管理学专业求职信
2014/06/05 职场文书
拆迁委托协议书
2014/09/15 职场文书
2015年中职班主任工作总结
2015/05/25 职场文书
导游词之永泰公主墓
2019/12/04 职场文书
Python 线程池模块之多线程操作代码
2021/05/20 Python