yit*_*zih 10 javascript browser download
我想在用户单击允许他们下载文件的超链接后将用户重定向到其他网页.但是,由于他们需要在打开/保存文件对话框中进行选择,因此我不想在他们接受下载之前重定向它们.
如何检测到他们执行了此操作?
dan*_*vis 11
正如我多年来维护download.js所发现的那样,根本没有办法告诉 JS(或者可能一般来说,见下文)用户选择使用下载打开/保存对话框做什么.这是一个常见的功能要求,多年来我一直在重复研究它.我可以自信地说这是不可能的; 如果有人能演示一种机械方式来确定任何文件的后提示用户操作,我会高兴地支付10倍的赏金!
此外,它不仅仅是JS规则的问题,浏览器下载和提示此类文件的方式使问题变得复杂.这意味着即使服务器也无法总是告诉发生了什么.对于一些特定情况,可能会有一些特定的解决方法,但它们并不漂亮或简单.
您可以强制您的用户"重新上传"下载的文件以<input type=file>进行验证,但这样做很麻烦,本地文件浏览对话框可能会让某些人感到惊讶.这是确保下载的唯一可靠方法,但对于非敏感应用程序来说,它非常严苛,并且在一些缺乏文件支持的"移动"平台上无法运行.
您也可以尝试从服务器端观看,向客户端发送消息,告知该文件已在服务器上命中.这里的问题是,一旦打开/保存对话框出现,下载就开始下载,尽管在后台无形中.这就是为什么如果你等一会儿"接受"一个大文件,它似乎一开始就快速下载.从服务器的角度来看,无论用户做什么,活动都是相同的.
对于一个巨大的文件,您可能会检测到整个文件没有被传输,这意味着用户点击了"取消",但这是一个复杂的同步过程,将状态从后端推送到客户端.它需要大量的自定义编程,包括套接字,PHP消息传递,EventSource等,但收效甚微.这也是一场与时间的竞赛,而且时间不确定; 并且建议不要放慢下载速度以提高用户满意度.
如果它是一个小文件,它会在用户甚至看到对话框之前进行物理下载,因此服务器将无用.还要考虑一些下载管理器扩展接管作业,并且不保证它们的行为与vanilla浏览器相同.强迫等待对于那些"永远""完成"下载的硬盘速度慢的人来说可能是危险的; 我们都经历过这种情况,并且无法继续,而"spinny"降低会降低用户满意度,温和地说.
简而言之,没有简单的方法,除了你知道需要很长时间下载的大文件外,一般都没办法.我花了很多血汗和泪水试图提供我的download.js用户的能力,但根本没有好的选择.Ryan dahl最初编写了node.js,因此他可以为他的用户提供一个上传进度条,也许有人会制作一个服务器/客户端软件包,以便在下载时轻松做同样的事情.
@dandavis
如果有人可以演示一种机械方式来确定用户对任何文件的提示后操作,我将很高兴地支付 10 倍的赏金!
你准备好了吗?因为这里是一个hacky解决方案
我的StreamSaver lib 不使用 blob 下载带有a[download]. 它使用 service worker 通过模拟服务器如何处理带有内容处理附件头的下载来将某些内容流式传输到光盘。
evt.respondWith(
new Response(
new ReadableStream({...})
)
)
Run Code Online (Sandbox Code Playgroud)
现在你没有任何确切的方法知道用户在对话框中按下了什么,但你有一些关于流的信息。
如果用户在对话框中按取消或中止正在进行的下载,则流也会中止。
保存按钮比较棘手。但是让我们从流桶 highWaterMark 可以告诉我们的内容开始。
在我的torrent 示例中,我记录了writer.desiredSize. 这是与它愿意接收多少数据的相关性。当您向流写入内容时,它会降低所需的大小(无论是计数策略还是字节策略)。如果它从未增加,则表示用户可能已暂停下载。当它低于 0 时,您写入的数据比用户要求的要多。
你写的每一个块都会返回一个承诺
writer.getWriter().write(uint8).then(() => {
// Chunk have been sent to the destination bucket
// and desiredSize increase again
})
Run Code Online (Sandbox Code Playgroud)
当桶未满时,该承诺将得到解决。但这并不意味着该块已写入磁盘,仅表示该块已从一个流传递到另一个流(从写入 -> 可读 -> 响应)并且通常会在开始时这样做流以及另一个较早的块已写入磁盘的时间。
如果空洞数据可以容纳在存储桶(内存)中,则写入流甚至可以在用户做出选择之前完成
将存储桶大小调整为低于数据可以提供帮助
因此,您可以假设 - 下载开始 - 完成 - 和暂停的时间,但您不确定,因为您没有收到任何事件(除了关闭流的中止)
请注意,如果您不支持Transferable 流,则 torrent 示例不会显示正确的大小,但如果您在 Service Worker 中执行所有操作,则可以解决此问题。(而不是在主线程中进行)
检测流何时结束就像
readableStream.pipeTo(fileStream).then(done)
Run Code Online (Sandbox Code Playgroud)
对于将来的参考,WICG/native-file-system可能会让您访问将文件写入光盘,但它必须在您继续之前解决提示对话框承诺,并且可能正是用户所要求的
有一些将blob保存为流的示例,如果您有兴趣,还可以将更多blob 保存为 zip
| 归档时间: |
|
| 查看次数: |
5864 次 |
| 最近记录: |