如何强制Chrome在下载URL时不打开“另存为”对话框?

10

Chrome构建版本:最新的33+版

一个Chrome扩展程序从当前查看的网站中提取某些URL,然后下载它们的子集(通常是数百个文件)。

期望行为:

文件将被下载到默认的下载文件夹中,不需要询问在哪里和以哪个文件名保存。

问题:

如果用户在Chrome->设置->高级设置->下载中启用了“在下载前询问每个文件保存位置”的选项,则在尝试同时下载例如100个文件时,Chrome会尝试打开100个SaveAs对话框并崩溃。

我尝试过:

  • 使用chrome.downloads.download(对象选项、回调函数)方法,并使用选项saveAs: false
  • 使用以下代码通过模拟鼠标事件来触发下载:
  • function saveAs(Url,filename){
      var blob=new Blob([''], {type:'application/octet-stream'}); 
      var url = webkitURL.createObjectURL(blob);
      var a = document.createElementNS('http://www.w3.org/1999/xhtml','a');
      a.href = Url;
      a.download = filename; 
      var e = document.createEvent('MouseEvents');
      e.initMouseEvent('click', false, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
      a.dispatchEvent(e);
      webkitURL.revokeObjectURL(url);
    }
    

3
我从未开发过Chrome扩展程序,但是从以前在Chrome中使用应用程序的经验来看,用户定义的偏好始终优先于应用程序行为。如果允许应用程序覆盖用户明确点击的某些内容,那将是一种安全漏洞。 - royse41
1
你能否将这些内容发布到一个服务中,让它生成一个zip文件,然后返回URL或b64,最后下载该zip文件吗?这样只需要一个弹出窗口。 - oooyaya
说什么? :D 我非常欣赏你的思维方式,但是不行啊,更合适的做法是告知用户只需取消一个设置或不要一次尝试下载100个项目,而不是强制用户在每次下载后解压缩文件。此外,这种行为是违反直觉的 - 所以用户还是需要被告知。我认为必须有一个更优雅的解决方案。 - QuteBits
1
即使具有“下载”权限的扩展程序表示不需要,它仍可能弹出“另存为”对话框,这可能是一个错误。请在http://crbug.com/new?上报告错误。 - Jeffrey Yasskin
我已经在最新的版本(35.0.1897.2 dev-m)上进行了检查 - 看起来您是正确的,确实是一个错误。两种方法都按预期工作。您能否将您的答案放置在实际答案而不是评论中?这样我就可以将其标记为正确答案。 - QuteBits
2个回答

1

编辑:我已经添加了完整的多文件下载示例代码,它不会显示SaveAs对话框。

您可以通过使用chrome.downloads API来实现此功能。

manifest.json

{
  "description": "Multiple file downloads without showing SaveAs Dialog",
  "background": {
     "scripts": [ "background.js" ],
     "persistent" : true
  },
  "content_scripts": [{
     "js": [ "content_script.js"],
     "matches": [ "<all_urls>" ],
     "run_at": "document_start"
  }],
  "manifest_version": 2,
  "name": "MultipleFileDownloads",
  "permissions": [ "downloads" ],
  "short_name": "MFD",
  "version": "0.0.0.1"
}

content_script.js

var DOWNLOAD_LIMIT = 100;

function downloadURL(url, filename, callback){
    chrome.runtime.sendMessage({
        download_url : url,
        filename : filename
    },function(){
        if(typeof callback == 'function'){
            callback();
        }
    })
}

function simulateFileDownload(i){
    if(i > DOWNLOAD_LIMIT){
        document.getElementById('download_btn').disabled = false;
        return false;
    }
    var blob = new Blob(['This is sample file '+i], {type:'text/plain'});
    var url = URL.createObjectURL(blob);
    downloadURL(url,'Sample-'+i+'.txt',function(){
        URL.revokeObjectURL(url);
        i++;
        simulateFileDownload(i);
    })
}

window.onload = function(){
    var btn = document.createElement('button');
    btn.id = 'download_btn';
    btn.style.cssText = 'position:fixed;top:10px;left:10px;width:140px;height:30px;z-index:1000000;';
    btn.textContent = 'Download Files';
    document.body.appendChild(btn);
    btn.addEventListener('click',function(){
        this.disabled = true;
        simulateFileDownload(0);
    })
}

background.js

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
    if(message.download_url){
        chrome.downloads.download({
            url : message.download_url,
            filename : message.filename,
            saveAs : false
        })
    }
});

你能分享完整的示例吗?我无法安装你分享的crx文件。 - Raju Singh
你好,你能分享一下源代码吗?我需要在Chrome应用程序中实现下载功能。 - Jitendra singh
1
在 Windows 7 上的 Chrome v53 中,即使使用此示例,对我来说“另存为”对话框也总是显示。顺便提一下,您有一个错别字:在 background.js 中,“message.url” 应该是 “message.download_url”。 - thdoan

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接