Cancel long running download

2019-09-02 07:50发布

问题:

I have a web application with a PHP server side language on NGINX. Via JS, a user is able to download a file which is constructed dynamically by PHP from a database that is very slow. Therefore, to receive the first bytes for printing takes about 20 seconds. Then, more data is continuously streamed out afterwards.

PHP:

header("Content-Disposition: attachment; filename=\"" . $filename . ".txt\"");
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Set-Cookie: fileDownload=" . $filename . "; path=/");   

while (Stream::MORE_DATA == $client->receive($data)) {
   print $data;
   flush();
}

This download is taking place via an iframe (and it has to stay as an iframe for other reasons):

iframe = document.createElement("iframe");
iframe.style.display = "none";
iframe.src = downloadFileUrl;
(document.getElementsByTagName("body")[0]).appendChild(iframe);

In the case the user wants to navigate to another page in a new window, the other page will not load until the download is complete because NGINX is only serving up one request at a time (I think). So I enabled a way for the user to cancel the download:

iframe.contentWindow.stop();
iframe.parentNode.removeChild(iframe);

This works successfully if the download is cancelled in that initial 20 seconds before the first part of the file printed. However, if cancelled after the first print, the file still continues to be downloaded even though the iframe is nullified.

Is there another way to completely abort the download other than canceling it manually via the download manager of an internet browser?

Maybe this can be solved with JavaScript, PHP or an NGINX config change? Thanks!

回答1:

So I still have not been able to figure out a way with JavaScript to cancel an already initiated download that appears in the download manager of a browser. But, using session_write_close after session_start will allow these concurrency issues to be avoided, and therefore, multiple PHP scripts to be ran simultaneuosly (i.e. the download can still occur while a user is navigating the page in a different window)

header("Content-Disposition: attachment; filename=\"" . $filename . ".txt\"");
header("Pragma: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Set-Cookie: fileDownload=" . $filename . "; path=/");   

session_write_close();
while (Stream::MORE_DATA == $client->receive($data)) {
   print $data;
   flush();
}