Skip to content

Commit

Permalink
MDL-38194 Files: Allow download of large backup files
Browse files Browse the repository at this point in the history
The PHP readfile function does not work for files more than 2GB.
This commit provides a wrapper that can be used so that files less
than 2GB are sent with readfile, and files larger than 2GB are
sent manually.

The change applies to all uses of pluginfile.php, although in
reality, backup files are probably the only ones likely to be more
than two gigabytes.
  • Loading branch information
sammarshallou committed Sep 13, 2013
1 parent e81fce9 commit da7c844
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
39 changes: 38 additions & 1 deletion lib/filelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1983,6 +1983,43 @@ function send_header_404() {
}
}

/**
* The readfile function can fail when files are larger than 2GB (even on 64-bit
* platforms). This wrapper uses readfile for small files and custom code for
* large ones.
*
* @param string $path Path to file
* @param int $filesize Size of file (if left out, will get it automatically)
* @return int|bool Size read (will always be $filesize) or false if failed
*/
function readfile_allow_large($path, $filesize = -1) {
// Automatically get size if not specified.
if ($filesize === -1) {
$filesize = filesize($path);
}
if ($filesize <= 2147483647) {
// If the file is up to 2^31 - 1, send it normally using readfile.
return readfile($path);
} else {
// For large files, read and output in 64KB chunks.
$handle = fopen($path, 'r');
if ($handle === false) {
return false;
}
$left = $filesize;
while ($left > 0) {
$size = min($left, 65536);
$buffer = fread($handle, $size);
if ($buffer === false) {
return false;
}
echo $buffer;
$left -= $size;
}
return $filesize;
}
}

/**
* Enhanced readfile() with optional acceleration.
* @param string|stored_file $file
Expand Down Expand Up @@ -2105,7 +2142,7 @@ function readfile_accel($file, $mimetype, $accelerate) {
if (is_object($file)) {
$file->readfile();
} else {
readfile($file);
readfile_allow_large($file, $filesize);
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/filestorage/stored_file.php
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ public function readfile() {
throw new file_exception('storedfilecannotread', '', $path);
}
}
readfile($path);
readfile_allow_large($path, $this->get_filesize());
}

/**
Expand Down

0 comments on commit da7c844

Please sign in to comment.