Limitation of parallel / simultaneous downloads. How do I know if a download has been canceled?

I have a simple file download service written in PHP, which also includes a script that controls the download speed by sending packets with a limited size when the user requests a download from this site.

I want to implement a system to limit parallel / simultaneous loading to 1 per user, if they are not participants in the award. In the downloadable script above, I can use the MySQL database to store a record that has: (1) user ID; (2) file identifier; (3) when starting the download; and (4) when sending the last packet, which is updated every time it is performed (if the DL speed is limited to 150 kB / s, then after every 150 kB this record is updated, etc.).

However, until now, the database record will be deleted only after the download is complete - at the end of the script, after the full download, the record download is deleted from the table:

insert DB record; while (download is being served) { serve packet of data; update DB record with current date/time; } // Download is now complete delete DB record; 

How can I detect when the download was canceled? Should I just have a Cron job (or something similar) to detect if the existing download record is more than X minutes / hours? Or is there something else I can do that is missing?

I hope I explained it quite well. I do not think that it is required to send a specific code; I'm more interested in the logistics of how to do this. If necessary, I gladly provided it.

NOTE. I know how to determine if a file was uploaded successfully; I need to know how to determine if it has been canceled, interrupted or otherwise stopped (and not just suspended). This will be useful to stop concurrent downloads, as well as to prevent the user from canceling download # 1 and trying to start Download # 2, only to find that the site claims that it is still downloading file # 1.

EDIT: you can find my download script here: http://codetidy.com/1319/ - it already supports multi-user downloads and resume downloads.

+2
source share
3 answers
 <?php class DownloadObserver { protected $file; public function __construct($file) { $this->file = $file; } public function send() { // -> note in DB you've started readfile($this->file); } public function __destruct() { // download is done, either completed or aborted $aborted = connection_aborted(); // -> note in DB } } $dl = new DownloadObserver("/tmp/whatever"); $dl->send(); 

should work fine. There is no need for shutdown_function or any funky do-it-yourself observations.

+4
source

You will need the following functions: connection_status (), connection_aborted () and ignore_user_abort () (see the link section in the PHP manual section for more information).

Although I cannot guarantee reliability (it has been a while since I played with it), with the right combination you can accomplish what you want. There are a few caveats when working with them, although the biggest one is that if something goes wrong, you may encounter twisted PHP scripts running on the server, requiring you to kill Apache to stop them.

The following should give you a good idea of ​​how to do this (adapted from sample PHP code and a few comments):

 <?php //Set PHP not to cancel execution if the connection is aborted //and drop the time limit to allow for big file downloads ignore_user_abort(true); set_time_limit(0); while(true){ //See the ignore_user_abort() docs re having to send data echo chr(0); //Make sure the data gets flushed properly or the connection check won't work flush(); ob_flush(); //Check then connection status and exit loop if aborted if(connection_status() != CONNECTION_NORMAL || connection_aborted()) break; //Just to provide some spacing in this example sleep(1); } file_put_contents("abort.txt", "aborted\n", FILE_APPEND); //Never hurts to ensure that the script halts execution die(); 

Obviously, for how you use it, the data you send will just load a piece of data (just make sure you dump the buffer correctly to ensure that the data is actually sent). As far as I know, there is no way to distinguish between pause and interrupt / stop. Pause / resume (and multi-user download β€” that is, how boot managers speed up the download) relies on the β€œRange” header, mostly requesting byte x for byte y of the file. Therefore, if you want to allow resuming downloads, you will also have to deal with this.

+1
source

The HTTP cancel signal is not sent by default. Thus, it looks like you will need to resolve the issue of timeout, the time during which the connection can sit without sending / receiving another packet. If you are sending fairly small packets (I suppose you are), the timeout is short for a better effect.

In the current state, you will need to check the age of the last timestamp update, if it is too old, stop sending the file.

0
source

Source: https://habr.com/ru/post/1398712/


All Articles