【问题标题】:Make browser download/save files without user interaction使浏览器无需用户交互即可下载/保存文件
【发布时间】:2014-02-03 17:20:07
【问题描述】:

我需要创建一个基于浏览器的小型应用程序,帮助用户下载/保存,并可能打印到默认打印机,来自我们无法控制的网络服务器的大量文件(但我们事先拥有所有 URI) .

这些文件隐藏在“单点登录”(SSO) 后面,只能通过浏览器执行并且需要用户。因此,它必须是基于浏览器的解决方案,我们在其中搭载 SSO 建立的会话。

用户的平台是Windows 7。

重点是在用户需要执行此操作时(每天),避免用户对每个文件进行大量点击(下载、保存位置等)。

此时所有文件都是 PDF,但将来可能会改变。

首选与浏览器无关的解决方案(我认为在未来的浏览器更新方面会更加稳健)。

但如果需要,我们可以将其基于特定的浏览器。

你会如何使用 Javascript 来做到这一点?

【问题讨论】:

  • 您是否尝试使用 Web 浏览器的下载管理器扩展程序?
  • 我认为浏览器安全模型不允许这样做。脚本无法在用户不知情的情况下创建文件。
  • 您不能在没有用户交互的情况下强制下载或打印任务。如果我把整个 Divina Commedia 作为一个笑话发送给你的打印机怎么办?
  • Firefox 是唯一能够轻松为附加开发人员提供此类功能的通用浏览器。 (好吧,如果您不介意下载最终位于预定义的文件夹(下载)中,那么 Chrome 也是一种选择,请参阅chrome.downloads);虽然您所描述的内容听起来很像“浏览器自动化”,但有一些现有的工具可以做到这一点,例如 Selenium
  • 一些用户交互没问题(开始/接受过程)。关键是避免用户对每个文件执行一次(或多次)点击。

标签: javascript browser download


【解决方案1】:

正如我的问题的 cmets 所说,出于安全原因,浏览器实际上不允许这样做。

我目前的解决方法(仅使用 IE11 测试)是手动更改用户浏览器的安全设置,然后使用 AJAX 将文件作为 blob 下载到 javascript 变量中,然后将相同的 blob 上传到我自己的服务器再次使用 AJAX。

“我自己的服务器”是为此目的创建的 Django 站点,它还知道当天要下载哪些文件,并提供所需的 javascript。用户在单独的浏览器选项卡中执行 SSO 后转到此站点以启动每日下载。

然后我可以在服务器上执行所述文件所需的任何操作。

非常感谢这篇帖子 https://stackoverflow.com/a/13887220/833320 在 AJAX 中处理二进制数据。

1) 在 IE 中,将涉及的站点添加到“本地 Intranet 区域”,并为该区域启用“跨域访问数据源”以克服 CORS 保护,否则会阻止这种情况。

当然,请考虑其中涉及的安全后果......

2) 在 javascript(浏览器)中,将文件作为 blob 下载并将生成的数据 POST 到我自己的服务器:

var x = new XMLHttpRequest();
x.onload = function() {
    // Create a form
    var fd = new FormData();
    fd.append('csrfmiddlewaretoken', '{{ csrf_token }}'); // Needed by Django
    fd.append('file', x.response); // x.response is a Blob object

    // Upload to your server
    var y = new XMLHttpRequest();
    y.onload = function() {
        alert('File uploaded!');
    };
    y.open('POST', '/django/upload/');
    y.send(fd);
};
x.open('GET', 'https://external.url', true);
x.responseType = 'blob';    // <-- This is necessary!
x.send();

3) 最后(在 '/django/upload/' 的 Django 视图中),接收上传的数据并保存为文件 - 或其他...

filedata = request.FILES['file'].read()

with open('filename', 'wb') as f:
    f.write(filedata)

谢谢大家,感谢你们的cmets。

是的,真正的解决方案是克服 SSO(需要用户),因此这一切都可以由服务器本身完成。

但至少我学到了一点关于使用现代 XMLHttpRequests 获取/发布二进制数据的知识。 :)

【讨论】:

    【解决方案2】:

    其实我也遇到过这样的问题,我想下载一个二进制文件(图片)并存储起来,在需要的时候使用,所以我决定用 Fetch API Get 调用下载它:

    const imageAddress = 'an-address-to-my-image.jpg'; // sample address
    
    fetch(imageAddress)
      .then(res => res.blob)  // <-- This is necessary!
      .then(blobFileToBase64)
      .then(base64FinalAnswer => console.log(base64FinalAnswer))
    

    blobFileToBase64 是一个辅助函数,将blob 二进制文件转换为base64 数据字符串:

    const blobToBase64 = blob => {
      const reader = new FileReader();
      reader.readAsDataURL(blob);
      return new Promise(resolve => {
        reader.onloadend = () => {
          resolve(reader.result);
        };
      });
    };
    

    最后,我有了base64FinalAnswer,我可以用它做任何事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-20
      • 2020-12-22
      • 1970-01-01
      • 2013-04-10
      • 2014-01-09
      • 2017-11-04
      • 2016-10-17
      • 1970-01-01
      相关资源
      最近更新 更多