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

Download a file stored in CRM from a php webpage

我有一个网站可以从我们的 CRM (SugarCRM) 中提取客户案例,案例和案例说明可以包含存储在 CRM 中的附件。 Sugar 有一个内置的 API 端点来获取文件数据,并 return 通过 curl 请求使用:

//:record/file/:字段作为 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, true);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0);
    curl_setopt($curl, 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, 0, $header_size);
    $file           = substr($response, $header_size);
    curl_close($curl);

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

    return $file;

我没有将编码设置为 true,所以只是 returning 原始文件而不是将其编码为 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脚本

    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 文件,但它无法打开,所以我想看看我在 headers

上做错了什么

我可以通过以下headers

获取各​​种文件下载
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 headers 后,我 download.php 使用以下代码成功下载存储在我的 CRM 中的文件

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

用于从 CRM 获取文件的 Curl 脚本

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, true);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            "OAuth-Token: ".self::$tokens->access_token,
        )
    );

    $response       = curl_exec($curl);
    $header_size    = curl_getinfo($curl,CURLINFO_HEADER_SIZE);
    $headers        = substr($response, 0, $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;
}