ChatGPT解决这个技术问题 Extra ChatGPT

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

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


m
mozgras

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

window.location.assign(url);

这与 window.location = url; 相同“每当为位置对象分配新值时,就会使用 URL 加载文档,就像使用修改后的 URL 调用 window.location.assign() 一样” - developer.mozilla.org/en-US/docs/Web/API/window.location
这会导致 WebSocket 连接断开。
我使用了相同的解决方案,但它在同一选项卡中打开文件,而不是打开下载对话框。
如果 url 用于下载页面,则它与 window.open(url, '_self') 相同。
使用 IE11 时,我发现这会导致 JS 停止。所以对于 IE 11,我使用了 window.open(url, '_blank') ,它确实打开了另一个选项卡,但是当它发现文件是下载时,该选项卡关闭了。这使 JS 保持运行。
D
Dcoder14

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);

@Manoj Rana - 我检查了 FF 58.0.2(64 位)它正在工作。如果您删除 2 行 document.body.appendChild(a); ,它将不适用于任何 FF; document.body.removeChild(a);
要使其在 Edge 16 上工作,文件来自的标头应包含 Content-Type: application/octet-streamContent-Disposition: attachment
@user1933131 chrome 仅针对跨域删除
@PauliusDragunas 它仍然有效。但它不适用于跨域网址。
c
cнŝdk

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

最佳解决方案:

JavaScript 中打开文件下载弹出窗口的最佳 working solution 是使用 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');

工作演示:

函数 downloadFile(filePath) { var link = document.createElement('a');链接.href = 文件路径; link.download = filePath.substr(filePath.lastIndexOf('/') + 1);链接.click(); } 下载文件(“http://www.adobe.com/content/dam/Adobe/en/accessibility/pdfs/accessing-pdf-sr.pdf”);

笔记:

您必须使用 link.download 属性,以便浏览器不会在新选项卡中打开文件并触发下载弹出窗口。

这已使用多种文件类型(docx、xlsx、png、pdf、...)进行了测试。


@Ctrl_Alt_Defeat 好吧,在这种情况下,跟踪下载过程并不容易,但一个技巧是在 link 单击时显示此 gif 动画并在超时后将其隐藏,使用以下代码:link.onclick = function() { document.body.innerText = "The file is being downloaded ..."; setTimeout(function() { document.body.innerText = ""; }, 2000); },您可以看到它在 in this fiddle 工作,但请记住,这不是推荐的方法,如果我们使用 Ajax 会更好地处理。
它在 Firefox 中不起作用。火狐怎么下载?
这个解决方案适用于我的 Chrome、Safari 和 Firefox :)
这看起来是我的情况的最佳方法
谢谢@cнŝdk!我删除了我之前的评论,因为我发现 PWA 在前往 document.createElement() 的过程中会中断其他事情。如果我清理它们,该方法仍然有效。
j
jao

我总是在下载链接中添加一个 target="_blank"。这将打开一个新窗口,但是一旦用户单击保存,新窗口就会关闭。


这是最好的答案。在 Internet Explorer 中,将 'target="_blank"' 添加到要下载的链接将阻止浏览器导航(打印“HTML1300: Navigation occurred”),从而使页面处于不一致状态。
c
ccondrup

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

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

然后把这个放到body里面,5秒后会自动开始下载:

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

(来自 here。)


这不起作用,因为在 IE6 中,如果用户单击“保存”,文件将被保存,但弹出窗口保持打开状态。这是不可接受的。
这段代码在 safari 中不起作用,你能帮我在 safari 中解决吗?
它正在浏览器的新窗口中打开。可以自动下载吗???谢谢
这在我们的主 2022 年不再有效
a
alockwood05

正如这个问题所暗示的那样,我一直在寻找一种使用 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();

好的。隐藏风格似乎有点过分。但我猜你真的不想看到那个框架。 :)
l
loretoparisi

使用 HTML5 Blob 对象 URL 文件 API:

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @see https://stackoverflow.com/questions/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

/** * 使用 HTML 临时元素和 Blob 将文本另存为文件 * @see https://stackoverflow.com/questions/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') { // 使用 Blob var textFileAsBlob = new Blob([fileContents ], { type: 'text/plain' }); var downloadLink = document.createElement("a"); downloadLink.download = 文件名; 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 = "无"; 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('下载', 文件名); 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(文件名,文件内容)


我觉得这是最好的方法!!
当不再需要文件来释放内存时,调用 URL.revokeObjectURL(url) 也是一个好习惯
B
Bnrdo

修改窗口的位置可能会导致一些问题,尤其是当您有像 websocket 这样的持久连接时。所以我总是求助于好的旧 iframe 解决方案。

HTML

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

Javascript

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();
}

I
IvanH

如果链接指向有效的文件 url,只需分配 window.location.href 即可。

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

执行正常的 event.preventDefault 以防止窗口打开,如果您使用的是 jQuery,这将起作用:

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

G
Gaurav Kunal

根据新 chrome 规范的最佳解决方案 https://developers.google.com/web/updates/2018/02/chrome-65-deprecations

香草 JavaScript

public static downloadFile(url: string): void {
     const xmlHttp = new XMLHttpRequest();
     xmlHttp.onreadystatechange = () => {
       if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
         const blobUrl = window.URL.createObjectURL(xmlHttp.response);
         const e = document.createElement('a');
         e.href = blobUrl;
         e.download = blobUrl.substr(blobUrl.lastIndexOf('/') + 1);
         document.body.appendChild(e);
         e.click();
         document.body.removeChild(e);
       }
     };
     xmlHttp.responseType = 'blob';
     xmlHttp.open('GET', url, true);
     xmlHttp.send(null);
   }

如果你使用角度试试这个。

async downloadBrochure(url: string) {
    try {
      const res = await this.httpClient.get(url, { responseType: 'blob' }).toPromise();
      this.downloadFile(res);
    } catch (e) {
      console.log(e.body.message);
    }
  }

  downloadFile(data) {
    const url = window.URL.createObjectURL(data);
    const e = document.createElement('a');
    e.href = url;
    e.download = url.substr(url.lastIndexOf('/') + 1);
    document.body.appendChild(e);
    e.click();
    document.body.removeChild(e);
  }

М
М.Б.

经过数小时的尝试,该功能诞生了 :) 我有一个场景,我必须在文件准备下载时及时显示加载程序:

在 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)
        }
    });

佚名

怎么样:

<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">');

问候


哇,伙计,这个反应很棒,正是我所需要的。十多年后的感谢
S
Simon

一个小的/隐藏的 iframe 可以用于此目的。

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


常量 downloadUrl = "网址"; const downloadFrame = document.getElementById('download-iframe') || document.createElement("iframe"); downloadFrame.setAttribute('src',downloadUrl); downloadFrame.setAttribute('id',"download-iframe"); downloadFrame.style.display = "无"; document.body.appendChild(downloadFrame);
我尝试了这个脚本,但我没有开始下载 - 只是加载到 iframe 中。