打开下载窗口而无需离开页面的最简单方法


118

跨浏览器打开下载对话框的最佳方法是什么(假设我们可以在标题中设置content-disposion:attachment)而无需离开当前页面或打开弹出窗口,而这在Internet Explorer(IE)中效果不佳)6。

Answers:


106

7年过去了,我不知道它是否适用于IE6,但这会在FF和Chrome中提示OpenFileDialog。

var file_path = 'host/path/file.ext';
var a = document.createElement('A');
a.href = file_path;
a.download = file_path.substr(file_path.lastIndexOf('/') + 1);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);

首先,感谢您提供此解决方案,但如果发现removeChild(a)zip将会解压缩zip的错误,我发现了一个错误,因此请删除此代码来解决它
Roy

2
@Manoj Rana-我检查了FF 58.0.2(64位)是否正常工作。如果删除两行,它将无法在任何FF上运行document.body.appendChild(a); document.body.removeChild(a);
0x000f

1
为了使其在Edge 16上运行,文件所在的标头应包含Content-Type: application/octet-streamContent-Disposition: attachment
西蒙(Simon)


2
@ user1933131铬只删除了跨域
Brandy23

200

这个javascript很不错,它不会打开新的窗口或标签。

window.location.assign(url);

17
这与window.location = url相同;“每当一个新的值被分配到该位置的对象中,文件将被使用URL加载仿佛window.location.assign()已经被称为与修改后的URL” - developer.mozilla.org/en-US/docs/ Web / API / window.location
Rob Juurlink,2013年

13
这将导致WebSocket连接断开。
igorpavlov '16

4
我使用了相同的解决方案,但它在同一选项卡中打开文件,而不是打开下载对话框。
Techno Cracker

2
如果该URL用于下载页面,则与window.open(url,'_self')相同。
专家希望成为

5
使用IE11时,我发现这导致JS停止。因此,对于IE 11,我使用window.open(url,'_blank')确实打开了另一个选项卡,但是在确定文件为下载文件时,该选项卡关闭了。这使JS保持运行。
路加福音

23

我总是将target =“ _ blank”添加到下载链接。这将打开一个新窗口,但是一旦用户单击“保存”,就会关闭新窗口。


2
这是最好的答案。在Internet Explorer中,将“ target =“ _ blank”'添加到要下载的链接中将阻止浏览器导航(打印“ HTML1300:导航发生”的位置),从而使页面处于不一致状态。
user64141

23

将其放在HTML标头部分,将urlvar 设置为要下载文件的URL:

<script type="text/javascript">  
function startDownload()  
{  
     var url='http://server/folder/file.ext';    
     window.open(url, 'Download');  
}  
</script>

然后将其放入正文中,它将在5秒钟后自动开始下载:

<script type="text/javascript">  
setTimeout('startDownload()', 5000); //starts download after 5 seconds  
</script> 

(从这里开始。)


2
那是行不通的,因为在IE6中,如果用户单击“保存”,则文件已保存,但弹出窗口保持打开状态。这是不可接受的。
mkoryak 2009年

该代码在Safari中不起作用,请您帮我解决一下。
Renish Khunt,2015年

17

我知道有人问过这个问题,7 years and 9 months ago但许多发布的解决方案似乎都行不通,例如,<iframe>仅与FireFox和不一起使用作品Chrome

最佳解决方案:

打开文件下载弹出窗口的最佳方法JavaScript是使用HTML链接元素,而无需将链接元素附加到document.body其他答案中所述。

您可以使用以下功能:

function downloadFile(filePath){
    var link=document.createElement('a');
    link.href = filePath;
    link.download = filePath.substr(filePath.lastIndexOf('/') + 1);
    link.click();
}

在我的应用程序中,我以这种方式使用它:

downloadFile('report/xls/myCustomReport.xlsx');

工作演示:

注意:

  • 您必须使用该link.download属性,以便浏览器不会在新选项卡中打开文件并触发下载弹出窗口。
  • 已使用多种文件类型(docx,xl​​sx,png,pdf等)对其进行了测试。

在下载文件之前显示加载gif的最佳方法是什么?
Ctrl_Alt_Defeat

1
@Ctrl_Alt_Defeat那么在这种情况下,它不会是容易跟踪下载过程,但一招可以显示在这个GIF动画link点击并在超时后隐藏它,使用此代码:link.onclick = function() { document.body.innerText = "The file is being downloaded ..."; setTimeout(function() { document.body.innerText = ""; }, 2000); },你可以看到它的工作这摆弄,但请记住,这不是推荐的方法,如果使用,则最好处理Ajax
cнŝdk

1
在Firefox中不起作用。如何在firefox中下载?
Manoj Rana

@ManojRana对于Firefox,您可以使用iframe参见此答案
cнŝdk

2
该解决方案在Chrome,Safari和Firefox的作品对我来说:)
ariebear

15

正如这个问题所暗示的那样,我一直在寻找一种使用javascript来启动文件下载的好方法。但是,这些答案没有帮助。然后,我进行了一些xbrowser测试,发现iframe在所有IE> 8的现代浏览器上均能最好地工作。

downloadUrl = "http://example.com/download/file.zip";
var downloadFrame = document.createElement("iframe"); 
downloadFrame.setAttribute('src',downloadUrl);
downloadFrame.setAttribute('class',"screenReaderText"); 
document.body.appendChild(downloadFrame); 

class="screenReaderText" 是我的课程,用来设置存在但不可见的内容的样式。

CSS:

.screenReaderText { 
  border: 0; 
  clip: rect(0 0 0 0); 
  height: 1px; 
  margin: -1px; 
  overflow: hidden; 
  padding: 0; 
  position: absolute; 
  width: 1px; 
}

与html5boilerplate中的.visuallyHidden相同

我更喜欢javascript window.open方法,因为如果链接断开,则iframe方法根本不执行任何操作,而重定向到空白页表示无法打开文件。

window.open(downloadUrl, 'download_window', 'toolbar=0,location=no,directories=0,status=0,scrollbars=0,resizeable=0,width=1,height=1,top=0,left=0');
window.focus();

6

使用HTML5 Blob对象URL文件API:

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see /programming/49988202/macos-webview-download-a-html5-blob-file
 * @param fileName String
 * @param fileContents String JSON String
 * @author Loreto Parisi
*/
var saveBlobAsFile = function(fileName,fileContents) {
    if(typeof(Blob)!='undefined') { // using Blob
        var textFileAsBlob = new Blob([fileContents], { type: 'text/plain' });
        var downloadLink = document.createElement("a");
        downloadLink.download = fileName;
        if (window.webkitURL != null) {
            downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
        }
        else {
            downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
            downloadLink.onclick = document.body.removeChild(event.target);
            downloadLink.style.display = "none";
            document.body.appendChild(downloadLink);
        }
        downloadLink.click();
    } else {
        var pp = document.createElement('a');
        pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
        pp.setAttribute('download', fileName);
        pp.onclick = document.body.removeChild(event.target);
        pp.click();
    }
}//saveBlobAsFile

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see /programming/49988202/macos-webview-download-a-html5-blob-file
 * @param fileName String
 * @param fileContents String JSON String
 * @author Loreto Parisi
 */
var saveBlobAsFile = function(fileName, fileContents) {
  if (typeof(Blob) != 'undefined') { // using Blob
    var textFileAsBlob = new Blob([fileContents], {
      type: 'text/plain'
    });
    var downloadLink = document.createElement("a");
    downloadLink.download = fileName;
    if (window.webkitURL != null) {
      downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
    } else {
      downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
      downloadLink.onclick = document.body.removeChild(event.target);
      downloadLink.style.display = "none";
      document.body.appendChild(downloadLink);
    }
    downloadLink.click();
  } else {
    var pp = document.createElement('a');
    pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
    pp.setAttribute('download', fileName);
    pp.onclick = document.body.removeChild(event.target);
    pp.click();
  }
} //saveBlobAsFile

var jsonObject = {
  "name": "John",
  "age": 31,
  "city": "New York"
};
var fileContents = JSON.stringify(jsonObject, null, 2);
var fileName = "data.json";

saveBlobAsFile(fileName, fileContents)


2
我觉得这是最好的方法!
库沙尔MK

1
URL.revokeObjectURL(url)当不再需要该文件来释放内存时,调用也是一个好习惯
SleepWalker

5

修改窗口的位置可能会引起一些问题,尤其是当您拥有像websocket这样的持久连接时。因此,我总是采用良好的旧iframe解决方案。

的HTML

<input type="button" onclick="downloadButtonClicked()" value="Download"/>
...
...
...
<iframe style="display:none;" name="hiddenIframe" id="hiddenIframe"></iframe>

Java脚本

function downloadButtonClicked() {
    // Simulate a link click
    var url = 'your_download_url_here';
    var elem = document.createElement('a');
    elem.href = url;
    elem.target = 'hiddenIframe';
    elem.click();
}

5

如果链接指向有效的文件URL,则只需分配window.location.href就可以。

但是,有时链接无效,因此需要iFrame。

进行常规的event.preventDefault来防止窗口打开,并且如果您使用的是jQuery,这将起作用:

$('<iframe>').attr('src', downloadThing.attr('href')).appendTo('body').on("load", function() {
   $(this).remove();
});

2

经过数小时的尝试,该函数诞生了:)我遇到了这样一种情况:必须在文件准备下载时及时显示加载程序:

在Chrome,Safari和Firefox中工作

function ajaxDownload(url, filename = 'file', method = 'get', data = {}, callbackSuccess = () => {}, callbackFail = () => {}) {
    $.ajax({
        url: url,
        method: 'GET',
        xhrFields: {
            responseType: 'blob'
        },
        success: function (data) {
            // create link element
            let a = document.createElement('a'), 
                url = window.URL.createObjectURL(data);

            // initialize 
            a.href = url;
            a.download = filename;

            // append element to the body, 
            // a must, due to Firefox
            document.body.appendChild(a);

            // trigger download
            a.click();

            // delay a bit deletion of the element
            setTimeout(function(){
                window.URL.revokeObjectURL(url);
                document.body.removeChild(a);
            }, 100);

            // invoke callback if any 
            callbackSuccess(data);
        },
        error: function (err) {
            // invoke fail callback if any
            callbackFail(err)
        }
    });

0

怎么样:

<meta http-equiv="refresh" content="5;url=http://site.com/file.ext">

这种方式适用于所有浏览器(我认为),并让您输入以下消息:“如果下载没有在五秒钟内开始,请单击此处。”

如果您需要使用javascript ..那么...

document.write('<meta http-equiv="refresh" content="5;url=http://site.com/file.ext">');

问候


0

小型/隐藏式iframe可以用于此目的。

这样,您不必担心关闭弹出窗口。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.