使用PHP的cURL:将文件下载到客户端会导致文件损坏

时间:2014-11-03 20:11:38

标签: php curl

使用我将在下面发布的脚本,我使用PHP中的cURL成功地将JPG,PNG或PPT(x)文件从服务器下载到客户端。但是,当我打开以这种方式保存的任何powerpoint文件时,我收到错误" PowerPoint在FILENAME.pptx中发现内容有问题。 Powerpoint可以尝试修复演示文稿。如果您信任此演示文稿的来源,请单击“修复”。"

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 
}

我没有正确关闭流吗?我不知道问题是什么。

注意:JPG和PNG文件打开正常。 &安培;点击"修复"成功打开文件。

1 个答案:

答案 0 :(得分:1)

从脚本中管理文件下载并不是一个好主意。由于您的文件位于您的网络服务器上,因此最好使用更强大的方法,例如:x_sendfile mod for apache:

https://tn123.org/mod_xsendfile/ ref

用法:

    header("X-Sendfile: $path_to_somefile");
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"$somefile\"");
    exit;

此外,使用您的脚本,您可以暂停和恢复下载(您应该手动管理RangeContent-Range标头,这很容易出错。