从php网页下载存储在CRM中的文件

问题描述

我有一个网站可以从我们的CRM(SugarCRM)中提取客户案例,案例和案例注释可以包含存储在CRM中的附件。 Sugar有一个内置的API端点,用于获取文件数据并使用以下命令通过curl请求将其返回:

// ::记录/文件/:字段作为GET请求

我的curl脚本

    public static function getAttachment($url,$encode = false) 
{
    self::connect_sugarcrm();

    $curl = curl_init(self::$SUGARENDPOINTURI.self::$API.$url);
    curl_setopt($curl,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_0);
    curl_setopt($curl,CURLOPT_HEADER,true);
    curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);
    curl_setopt($curl,CURLOPT_RETURNTRANSFER,CURLOPT_FOLLOWLOCATION,CURLOPT_HTTPHEADER,array(
            "Authorization: Bearer","OAuth-Token: ".self::$tokens->access_token,)
    );

    $response       = curl_exec($curl);
    $header_size    = curl_getinfo($curl,CURLINFO_HEADER_SIZE);
    $headers        = substr($response,$header_size);
    $file           = substr($response,$header_size);
    curl_close($curl);

    if ($encode) {
        return base64_encode($file);
    }

    return $file;

我没有将编码设置为true,所以只是返回原始文件,而不是将其编码为Base64。如文档所述,我从CRM中得到了正确的答复。

HTTP/1.1 200 OK
Date: Fri,16 Oct 2020 14:01:10 GMT
Server: Apache/2.4.29 (Ubuntu)
Expires: 
Cache-Control: max-age=0,private
Pragma: 
Content-disposition: attachment; filename="copy of Countries by region.xlsx"
X-Content-Type-Options: nosniff
ETag: d41d8cd98f00b204e9800998ecf8427e
Content-Length: 59349
Connection: close
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet

我现在正试图弄清楚如何使浏览器下载此文件。在初始化下载之前,我需要在本地保存此文件吗?还是有一种方法可以下载它?

我的标题脚本

    header("Content-Description: File Transfer");
    header('Content-disposition: attachment; filename="copy of Countries by region.xlsx"');
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: 59349');
    // echo base64_decode($data);
    echo $file;
    exit();

这将下载一个56KB的excel文件,但无法打开,所以我想看看标题做错了什么

我可以使用以下标题下载各种文件

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-disposition: attachment; filename=\"{$file->name}\""); 
header('Expires: 0');
header('Cache-Control: must-revalidate,post-check=0,pre-check=0');
header('Pragma: public');
header("Content-Length: ".$file->{'content-length'}."");
ob_clean();
flush();

echo $data;
exit;

但是,这会导致某些文件类型(例如psd xslx)出错,但适用于jpg,png,gif,pdf,docx,csv

解决方法

进一步阅读PHP标头后,我获得了download.php,可以使用以下代码成功下载存储在CRM中的文件

ref:https://www.media-division.com/the-right-way-to-handle-file-downloads-in-php/

卷曲脚本以从CRM提取文件

public static function download($url)
{
    self::connect_sugarcrm();

    $curl = curl_init(self::$SUGARENDPOINTURI.$url);
    curl_setopt($curl,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_0);
    curl_setopt($curl,CURLOPT_HEADER,true);
    curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);
    curl_setopt($curl,CURLOPT_RETURNTRANSFER,CURLOPT_FOLLOWLOCATION,CURLOPT_HTTPHEADER,array(
            "OAuth-Token: ".self::$tokens->access_token,)
    );

    $response       = curl_exec($curl);
    $header_size    = curl_getinfo($curl,CURLINFO_HEADER_SIZE);
    $headers        = substr($response,$header_size);
    $file           = substr($response,$header_size);

    curl_close($curl);
    return $file;
}

Download.php

$module         = get_query_var('module');
$id             = get_query_var('id');
$url            = "{$module}/{$id}/file";
$fileinfo       = MagiConnect_SugarCRM::getSugar('',$url);

foreach ($fileinfo as $file) {
    $data       = MagiConnect_SugarCRM::download($file->uri);

    ob_end_clean();
    header("Content-Description: File Transfer");
    header("Content-Type: ".$file->{'content-type'});
    header("Content-Transfer-Encoding: Binary");
    header("Content-Disposition: attachment; filename=\"{$file->name}\""); 
    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: ".$file->{'content-length'}."");

    echo $data;
    exit;
}