Downloading the large (ish) zip that comes with PHP is corrupted for people with slow connections

I am a beginner, so I will try my best to explain the problem that I am experiencing. I apologize in advance if there is something I forgot or is unclear.

I maintain the 81MB zip file outside of my root directory for people who have verified in advance. I get messages about damaged downloads or inability to complete the download. I checked this on my machine if I simulate a slow connection.

I work on shared hosting Apache-Coyote / 1.1.

I get a network timeout error. I think my host can kill downloads if they take too much time, but they have not confirmed anyway.

I thought that maybe I'm working with a time limit or time limit, so my host installed the apache XSendFile module. My headers in the file that handles the download after verification are set as follows:

<?php set_time_limit(0); $file = '/absolute/path/to/myzip/myzip.zip'; header("X-Sendfile: $file"); header("Content-type: application/zip"); header('Content-Disposition: attachment; filename="' . basename($file) . '"'); 

Any help or suggestions would be appreciated. Thanks!

+4
source share
1 answer

I would suggest taking a look at this comment:

http://www.php.net/manual/en/function.readfile.php#99406

In particular, if you are using apache. If the code above should not be useful:

I had problems when I had really large files sent to clients with very slow download speeds. In these cases, the script will time out and the download will complete with an incomplete file. I am disconnected from disabling script timeouts - any time that is a solution to a programming problem, you are doing something wrong - so I tried to scale the timeout based on file size. This ultimately failed, although it is impossible to predict the speed at which the end user will upload the file, so that was just the best guess, so we inevitably get script timeouts messages.

Then I came across a fantastic Apache module called mod_xsendfile ( https://tn123.org/mod_xsendfile/ (binaries) or https://github.com/nmaier/mod_xsendfile (source)). This module basically controls the output buffer for the presence of special headers, and when it finds them, it runs apache to send the file to it, almost as if the user had requested the file directly. PHP processing stops at this point, so timeout errors, regardless of file size or client download speed. And finally, the client gets all the benefits of Apache sending the file, for example, an accurate report on the file size and the download status bar.

The code that I finally finished is too long to publish here, but generally uses the mod_xsendfile module if it is present, and if not, the script returns to using the code that I originally posted. You can find the example code at https://gist.github.com/854168

EDIT

Just to have a link to the code that executes the "chunking" Link to the source code :

 <?php function readfile_chunked ($filename,$type='array') { $chunk_array=array(); $chunksize = 1*(1024*1024); // how many bytes per chunk $buffer = ''; $handle = fopen($filename, 'rb'); if ($handle === false) { return false; } while (!feof($handle)) { switch($type) { case'array': // Returns Lines Array like file() $lines[] = fgets($handle, $chunksize); break; case'string': // Returns Lines String like file_get_contents() $lines = fread($handle, $chunksize); break; } } fclose($handle); return $lines; } ?> 
+2
source

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


All Articles