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 相关文章推荐
Google Map API更新实现用户自定义标注坐标
Jul 29 Javascript
js替换字符串的所有示例代码
Jul 23 Javascript
jquery ajax方式直接提交整个表单核心代码
Aug 15 Javascript
javascript获取设置div的高度和宽度兼容任何浏览器
Sep 22 Javascript
jQuery.lazyload+masonry改良图片瀑布流代码
Jun 20 Javascript
详解AngularJS如何实现跨域请求
Aug 22 Javascript
AngularJS实现单独作用域内的数据操作
Sep 05 Javascript
使用Angular.js实现简单的购物车功能
Nov 21 Javascript
vue Render中slots的使用的实例代码
Jul 19 Javascript
JS 音频可视化插件Wavesurfer.js的使用教程
Oct 31 Javascript
浅析Vue中拆分视图层代码的5点建议
Aug 15 Javascript
Vue组件间的通信pubsub-js实现步骤解析
Mar 11 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控制用户的浏览器--ob*函数的使用说明
2007/03/16 PHP
php接口和抽象类使用示例详解
2014/03/02 PHP
通过curl模拟post和get方式提交的表单类
2014/04/23 PHP
php使用simplexml_load_file加载XML文件并显示XML的方法
2015/03/19 PHP
ThinkPHP数据操作方法总结
2015/09/28 PHP
jQuery 判断页面元素是否存在的代码
2009/08/14 Javascript
JQuery 选择器 xpath 语法应用
2010/05/13 Javascript
js严格模式总结(分享)
2016/08/22 Javascript
JS中BOM相关知识点总结(必看篇)
2016/11/22 Javascript
BootStrap Datepicker 插件修改为默认中文的实现方法
2017/02/10 Javascript
Js经典案例的实例代码
2018/05/10 Javascript
详解vue中axios请求的封装
2019/04/08 Javascript
npm 语义版本控制详解
2019/09/10 Javascript
Element Steps步骤条的使用方法
2020/07/26 Javascript
python实现随机密码字典生成器示例
2014/04/09 Python
python3之微信文章爬虫实例讲解
2017/07/12 Python
python中类和实例如何绑定属性与方法示例详解
2017/08/18 Python
python机器学习之随机森林(七)
2018/03/26 Python
python实现守护进程、守护线程、守护非守护并行
2018/05/05 Python
Python selenium抓取微博内容的示例代码
2018/05/17 Python
Python使用到第三方库PyMuPDF图片与pdf相互转换
2019/05/03 Python
linux下安装python3和对应的pip环境教程详解
2019/07/01 Python
使用python获取邮箱邮件的设置方法
2019/09/20 Python
pandas中遍历dataframe的每一个元素的实现
2019/10/23 Python
对python中list的五种查找方法说明
2020/07/13 Python
使用豆瓣源来安装python中的第三方库方法
2021/01/26 Python
CSS3中的display:grid,网格布局介绍
2019/10/30 HTML / CSS
科沃斯机器人官网商城:Ecovacs
2016/08/29 全球购物
美国网上购买眼镜:Eyeconic
2017/07/29 全球购物
海滩咖啡馆:Beach Cafe
2018/02/02 全球购物
意大利包包和行李箱销售网站:Bagaglio.it
2021/03/02 全球购物
大学生交通专业求职信
2014/09/01 职场文书
民事申诉状范本
2015/05/20 职场文书
靠谱准确的求职信
2019/04/02 职场文书
PyTorch 如何检查模型梯度是否可导
2021/06/05 Python
JavaScript实现队列结构过程
2021/12/06 Javascript