Reputation: 7
Using the script I will post below, I successfully download JPG, PNG or PPT(x) files from server to the client using cURL in PHP. However, when I open any of the powerpoint files I save in this manner I get an error "PowerPoint found a problem with content in FILENAME.pptx. Powerpoint can attempt to repair the presentation. If you trust the source of this presentation, click Repair."
function download_file( $linkRequested = '', $whichFileToDownload = '' )
{
// literal dam reference. We dont want wider access to our files.
$fileWithPath = $_SERVER['HTTP_HOST'] . '/files/xxxXXX/specific/' . $whichFileToDownload;
/*** define the file type for the download MT ***/
// set generic mime type, in case we don't match
$mimeType = 'application/octet-stream';
// JPG
if ( preg_match('|\.jpg$|i', $whichFileToDownload) ) {
$mimeType = 'IMAGETYPE_JPEG';
}
// PNG
if ( preg_match('|\.png$|i', $whichFileToDownload) ) {
$mimeType = 'IMAGETYPE_PNG';
}
// older PowerPoint
if ( preg_match('|\.ppt$|i', $whichFileToDownload) ) {
$mimeType = 'application/vnd.ms-powerpoint';
}
// PowerPoint
if ( preg_match('|\.pptx$|i', $whichFileToDownload) ) {
$mimeType = 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
}
/*** do curl MT ***/
$ch = curl_init($fileWithPath);
curl_setopt( $ch, CURLOPT_URL, $fileWithPath );
$fp = fopen($fileWithPath, 'wb');
// set the curl options. Order is important.
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FILE, $fp);
// get the contents of the file as text
$content = curl_exec($ch);
// describe the file header for the client
header('Content-Description: File Transfer');
// set mime type for download of binary data
header('Content-Type: ' . $mimeType);
// Attachment indicates save the file. Filename sets file name
header('Content-Disposition: attachment; filename="' . $whichFileToDownload . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . strlen($content));
// send the file
ob_clean();
flush();
echo $content;
// clean up loose ends
flush();
curl_close($ch);
fclose($fp);
// don't return anything
}
Am I not closing the stream correctly? I don't know what the problem is.
Notes: JPG and PNG files open fine. & Clicking on "repair" successfully opens the file.
Upvotes: 1
Views: 1009
Reputation: 48101
Acutally managing file download from the script isn't a good idea. Since your files are on your webserver it's better if you use a more robust approach such as: x_sendfile
mod for apache:
https://tn123.org/mod_xsendfile/ ref
Usage:
header("X-Sendfile: $path_to_somefile");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$somefile\"");
exit;
Also, with your script you are giving away the possibility to pause and resume the download (you should manually manage Range
and Content-Range
header, and this is error-prone).
Upvotes: 1