简体   繁体   English

强制浏览器下载大文件

[英]Force browser download a large file

I'm using a POST request with body to dynamically create a specified file on the server side and streaming it to the client as a response. 我正在使用带有body的POST请求在服务器端动态创建指定文件,并将其作为响应流式传输到客户端。 The problem on the client side is that the file is being downloaded into the response object (browser's cache memory I suppose, as a temporary file) instead of the PC's hard drive. 客户端的问题是文件被下载到响应对象(浏览器的缓存内存,我想,作为临时文件)而不是PC的硬盘驱动器。

How can I pass the byte stream directly for the browser to handle and direct into the /Downloads folder or wherever the user has set the downloads go? 如何直接传递字节流以供浏览器处理和直接进入/ Downloads文件夹或用户设置下载的位置?

The file size is really large and there's not enough space on the gadget's hard drive to create it there and give a link for GET request. 文件大小非常大,小工具的硬盘驱动器上没有足够的空间来创建它并为GET请求提供链接。 So I need to create it on the fly and stream to the client as a POST response. 所以我需要动态创建它并作为POST响应流式传输到客户端。

Right now I've written my code in Angular, but the language doesn't really matter. 现在我已经在Angular中编写了我的代码,但语言并不重要。 I'd like to understand how the browser handles the situation. 我想了解浏览器如何处理这种情况。
When I execute the HTTP request, I bet the browser does something with it before it's passed to the socket. 当我执行HTTP请求时,我打赌浏览器在传递给套接字之前对它做了一些事情。 And I'm sure the browser does something with the received request too before passing it to the piece of code which performed the request. 而且我确定浏览器在将其传递给执行请求的代码片段之前也会对收到的请求执行某些操作。

I mean can you only by setting the response headers make the browser download the file into /Downloads? 我的意思是你能否只通过设置响应头使浏览器将文件下载到/ Downloads? What happens then to the waiting HTTP request if the packets are "stolen" by the browser? 如果数据包被浏览器“窃取”,那么等待的HTTP请求会发生什么? Or when the response headers arrive to the response object, can you somehow notify the browser that the body of the response is a file byte stream we wish to download into /Downloads? 或者当响应头到达响应对象时,您能以某种方式通知浏览器响应的主体是我们希望下载到/下载的文件字节流吗?

And I have the possibility to modify my server code too. 而且我也可以修改我的服务器代码。

EDIT More detailed explanation: 编辑更详细的解释:
My server is sending the 5GB file to the client. 我的服务器正在向客户端发送5GB文件。 Instead of just receiving that file in the temporary memory of the browser I would like to save the file directly on hard drive. 我不想直接在浏览器的临时内存中接收该文件,而是将文件直接保存在硬盘上。
But naturally the browser prevents the direct access to the users computer so I can't write it there. 但是,浏览器自然会阻止直接访问用户计算机,因此我无法在那里编写它。 So how do I pass the byte stream for the browser to handle and save into a file? 那么如何传递字节流以供浏览器处理并保存到文件中?

Ok, I have solved the problem. 好的,我已经解决了这个问题。 So if you send a file request yourself to the server from your javascript code the browser will just pass the received response directly to your response object, but you can't store it on the hard drive without some external (browser supported) tools. 因此,如果您从javascript代码向服务器发送文件请求,浏览器将直接将收到的响应传递给您的响应对象,但如果没有外部(浏览器支持的)工具,则无法将其存储在硬盘驱动器上。

What I mean is that if you perform any kind of $http.post() or .get() from your scripts the response will be passed to the $http.post().then(function(response){...}) directly and it's passed only after the whole response is received. 我的意思是,如果你从脚本中执行任何类型的$ http.post()或.get(),响应将被传递给$ http.post()。然后(function(response){...} )直接并且仅在收到整个响应后才通过。 Meaning that if you're expecting a file with the size of 5GB it will fail for being too large to be received inside the response object. 这意味着如果您期望一个大小为5GB的文件,它将因为太大而无法在响应对象中被接收而失败。

Instead what you have to do is to trigger the download in another way. 相反,您需要做的是以另一种方式触发下载。 What I did in my code is that I built a hidden 我在代码中所做的是我构建了一个隐藏的代码

<form method="POST" action="/set.uri.here/" id="download">...</form>

and when the user clicks the button to download the file, I run a function that builds the body of the form and then submits it. 当用户单击按钮下载文件时,我运行一个函数来构建表单的主体,然后提交它。 Which looks like 看起来像

var form = document.getElementById("download"); // magic here... create the body for the form and so on form.submit();

This way you can pass the request to be done by your browser so that then the response will be also handled by the browser. 这样您就可以通过浏览器传递请求,然后浏览器也会处理响应。 This is the crucial difference between doing the request yourself or by the browser. 这是您自己或浏览器执行请求之间的关键区别。 If you do the request yourself then the browser won't download the object but you will receive it yourself to do something with it. 如果您自己提出请求,那么浏览器将不会下载该对象,但您将自己接收它以对其进行操作。

If you wish the browser to download the object, then, make the browser do the request for the object as well! 如果您希望浏览器下载该对象,那么,让浏览器也为该对象做请求!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM