通过JavaScript下载文件到本地的方法(单文件)

最近在做一个文件下载的功能,这里把做的过程中用的技术和坑简要总结下。

1. 单文件下载(a标签)

同源单文件

针对单文件的情况下,同源的文件,可以通过 < a> 标签的 download 属性下载文件

 const elt = document.createElement('a');
 elt.setAttribute('href', url);
 elt.setAttribute('download', 'file.png');
 elt.style.display = 'none';
 document.body.appendChild(elt);
 elt.click();
 document.body.removeChild(elt);

但是这个方案并不适用于非同源的资源,此时它相当于普通的超链接,点击会跳转到资源页面,而不是下载。

非同源图片

如果不存在CORS问题, 可以借助Blob实现下载(构造xhr请求文件地址, 以Blob的形式接收Response):

function downloadWithBlob(url) {
 fetch(url).then(res => res.blob().then(blob => {
  var a = document.createElement('a');
  var url = window.URL.createObjectURL(blob);
  var filename = 'file.png';
  a.href = url;
  a.download = filename;
  a.click();
  window.URL.revokeObjectURL(url);
 }));
}

如果存在CORS问题,可以考虑使用 canvas 将图片转换成 base64 编码之后再通过 标签的 download 属性下载

function downloadPic(url) {
 const img = new Image;
 const canvas = document.createElement('canvas');
 const ctx = canvas.getContext('2d');
 img.onload = function() {
  canvas.width = this.width;
  canvas.height = this.height;
  ctx.drawImage(this, 0, 0);

  const elt = document.createElement('a');
  elt.setAttribute('href', canvas.toDataURL('image/png'));
  elt.setAttribute('download', 'file.png');
  elt.style.display = 'none';
  document.body.appendChild(elt);
  elt.click();
  document.body.removeChild(elt);
 };
 img.crossOrigin = 'anonymous';
 img.src = url;
}

2. 单文件下载(iframe)

iframe方式是在页面内隐藏iframe, 然后将下载地址加载到iframe中, 从而触发浏览器的下载行为

 const iframe = document.createElement('iframe');
 iframe.src = url;
 iframe.style.display = 'none';
 document.body.appendChild(iframe);

但是这里发现,即使是同域的图片,也无法完成下载,这是为啥呢?

这里就有个上面的a链接下载没有提到的问题:什么样的链接才能触发浏览器的下载:

url如何触发浏览器自动下载

一个url能否触发浏览器自动下载,主要看该请求响应头response header是否满足,一般是看Content-Disposition和Content-Type这两个消息头:

  • response header中指定了Content-Disposition为attachment,它表示让浏览器把消息体以附件的形式下载并保存到本地 (一般还会指定filename, 下载的文件名默认就是filename)
  • response header中指定了Content-Type 为 application/octet-stream(无类型) 或 application/zip(zip包时)等等。(其中 application/octet-stream表示http response为二进制流(没指定明确的type), 用在未知的应用程序文件,浏览器一般不会自动执行或询问执行。浏览器会像对待 设置了HTTP头Content-Disposition 值为 attachment 的文件一样来对待这类文件)

只要url满足上述触发的要求,那么都可以通过iframe的形式来下载

3. 代理服务处理下载

如果后端自己也能控制的话,或者后端能配合的话,可以写一个代理服务,在后端去请求文件数据,然后设置好相应的response header, 然后前端请求代理服务来做下载。

前端(假设代理服务接口是http://exampale.com/download):

 const downloadUrl = 'http://exampale.com/download?url=' + encodeURIComponent(url) + '&name=xxx';
 const elt = document.createElement('a');
 elt.setAttribute('href', downloadUrl);
 elt.setAttribute('download', 'file.png');
 ...

后端

const url = decodeURIComponent(req.query.url);
http.get(url, (response) => {
 res.setHeader('Content-disposition', 'attachment;filename=' + req.query.name);
 res.setHeader('Content-type', 'application/octet-stream');
 response.pipe(res);
});

单文件的处理先写到这里,多文件的下载下篇在写。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • JS实现弹出下载对话框及常见文件类型的下载

    1.写在前面 JS要实现下载功能,一般都是这么几个过程:生成下载的URL,动态创建一个A标签,并将其href指向生成的URL,然后触发A标签的单击事件,这样就会弹出下载对话框,从而实现了一个下载的功能. 这里所说的下载,有时候也可以理解为保存.出于安全考虑,JS肯定无法直接调用FileAPI写文件到磁盘,但是却可以通过下载来变相实现保存功能. 2.几个备用知识点 2.1. JS触发单击事件 既然是用A标签模拟,那么肯定要知道JS如何主动触发单击事件. 最简单的触发单击事件肯定是elem.clic

  • js自定义方法通过隐藏iframe实现文件下载

    通过隐藏iframe实现文件下载的js方法 复制代码 代码如下: <script> function download() { //下载文件的地址 var url="http://music.baidu.com/data/music/file?link=http://zhangmenshiting.baidu.com/data2/music/13618994/13618995183600128.mp3?xcode=48d4a720fcd9a974586066d0145f7207&qu

  • 用JS在浏览器中创建下载文件

    但受限于浏览器,很多情况下我们都只能给出个链接,让用户点击打开->另存为.如下面这个链接: 复制代码 代码如下: <a href="file.js">file.js</a> 用户点击这个链接的时候,浏览器会打开并显示链接指向的文件内容,显然,这并没有实现我们的需求.HTML5中给a标签增加了一个download属性,只要有这个属性,点击这个链接时浏览器就不在打开链接指向的文件,而是改为下载(目前只有chrome.firefox和opera支持). 下载时会

  • 使用JS代码实现点击按钮下载文件

    正文 有时候我们在网页上需要增加一个下载按钮,让用户能够点击后下载页面上的资料,那么怎样才能实现功能呢?这里有两种方法: 现在需要在页面上添加一个下载按钮,点击按钮下载文件. 题外话,这个下载图标是引用的 font-awesome 上面的.使用时,首先将 font-awesome 整个文件夹下载下来,利用bower或者是自己去官网上面下载都行. 将整个文件夹放在项目文件中之后,在页面上面引入css文件 <link href="libs/font-awesome-4.7.0/css/font

  • 用js实现下载远程文件并保存在本地的脚本

    //use: cscript this.js http://www.xxx.com/xxx.exe c:\xxx.exe var objArgs = WScript.Arguments; var sGet=new ActiveXObject("ADODB.Stream"); var xGet = false; try { xGet = new XMLHttpRequest(); }  catch (trymicrosoft) { try {     xGet = new ActiveX

  • js自动下载文件到本地的实现代码

    复制代码 代码如下: <html> <head> <title>js自动下载文件到本地</title> <script language="javascript" type="text/javascript"> function InitAjax() { var ajax; if(window.ActiveXObject){ var versions = ['Microsoft.XMLHTTP', 'MSX

  • JavaScript实现写入文件到本地的方法【基于FileSaver.js插件】

    本文实例讲述了JavaScript实现写入文件到本地的方法.分享给大家供大家参考,具体如下: 工作中有时需要通过 JavaScript 保存文件到本地,我们都知道 JavaScript 基于安全的考虑,是不允许直接操作本地文件的. IE 可以通过 VB 插件的方式进行,而 Chrome 和 firefox 都不支持 JavaScript 向本地写入文件,所以 VB 插件的方式存在兼容性问题. 那有没有适合的方法呢?答案是肯定的,我们可以通过 FileSaver.js 这个小插件实现我们的需求.下

  • 使用urllib库的urlretrieve()方法下载网络文件到本地的方法

    概述 见源码 源码 # !/usr/bin/env python # -*- coding:utf-8 -*- """ 图片(文件)下载,核心方法是 urllib.urlrequest 模块的 urlretrieve()方法 urlretrieve(url, filename=None, reporthook=None, data=None) url: 文件url filename: 保存到本地时,使用的文件(路径)名称 reporthook: 文件传输时的回调函数 data

  • php生成并下载word文件到本地实现方法详解

    目录 安装phpword包 准备一个word模板(docx格式) 前端调用代码 PHP处理代码 one more thing 安装phpword包 通过composer安装phpword包.因为是使用thinkphp架构,安装挺方便的. 直接下载phpword压缩包有问题. composer require phpoffice/phpword 准备一个word模板(docx格式) 准备好word模板后,只需要用变量替换需要替换的值,如下图所示,将房东名替换成${name}. 前端调用代码 系统前

  • php获取远程图片并下载保存到本地的方法分析

    本文实例讲述了php获取远程图片并下载保存到本地的方法.分享给大家供大家参考,具体如下: 远程图片指的是远端服务器上的数据我们可以通过php的许多函数来读取下载了,这里整理了两个可以自动下载远程图片并下载保存到本地的例子. 例1,可以自动识别图片类型然后进行对应的保存 /* *功能:php完美实现下载远程图片保存到本地 *参数:文件url,保存文件目录,保存文件名称,使用的下载方式 *当保存文件名称为空时则使用远程文件原来的名称 */ function getImage($url,$save_d

  • Python保存MongoDB上的文件到本地的方法

    本文实例讲述了Python保存MongoDB上的文件到本地的方法.分享给大家供大家参考,具体如下: MongoDB上的文档通过GridFS来操作,Python也可以通过pymongo连接MongoDB数据库,使用pymongo模块的gridfs方法操作文档.以下示例是把MongoDB上GridFS存的excel文档保存到本地. from pymongo import MongoClient import gridfs client = MongoClient('mongodb://usernam

  • java实现从网上下载图片到本地的方法

    本文实例讲述了java实现从网上下载图片到本地的方法.分享给大家供大家参考.具体如下: import java.io.*; import java.net.MalformedURLException; import java.net.URL; public static void writeFile(String strUrl,String fileName){ URL url = null; try { url = new URL(strUrl); } catch (MalformedURLE

  • Android Studio中生成aar文件及本地方式使用aar文件的方法

    主要讲解Android Studio中生成aar文件以及本地方式使用aar文件的方法,具体内容详情如下所示: 在Android Studio中对一个自己库进行生成操作时将会同时生成*.jar与*.aar文件. 分别存储位置: *.jar:库/build/intermediates/bundles/debug(release)/classes.jar *.aar:库/build/outputs/aar/libraryname.aar 两者区别: *.jar:只包含了class文件与清单文件,不包含

  • 通过JavaScript下载文件到本地的方法(单文件)

    最近在做一个文件下载的功能,这里把做的过程中用的技术和坑简要总结下. 1. 单文件下载(a标签) 同源单文件 针对单文件的情况下,同源的文件,可以通过 < a> 标签的 download 属性下载文件 const elt = document.createElement('a'); elt.setAttribute('href', url); elt.setAttribute('download', 'file.png'); elt.style.display = 'none'; docume

  • javascript 保存文件到本地实现方法

    2种形式都可以 第一种: 复制代码 代码如下: <script> function SaveAs5(imgURL) { var oPop = window.open(imgURL,"","width=1, height=1, top=5000, left=5000"); for(; oPop.document.readyState != "complete"; ) { if (oPop.document.readyState == &

  • php 替换文章中的图片路径,下载图片到本地服务器的方法

    php 替换文章中的图片路径,下载图片到本地服务器 /** * 获取替换文章中的图片路径 * @param string $xstr 内容 * @param string $oriweb 网址 * @return string * */ function replaceimg($xstr, $oriweb){ //保存路径 $d = date('Ymd', time()); $saveimgfile_1 = '/uploads/allimg/'.$d; $dirslsitss = DEDEROO

随机推荐