在CakePHP 2中下载动态生成的PNG

问题描述

我有一个动态生成的QR码PNG。我可以通过访问www.example.com/events/qrgen来访问它,这将使其正确显示在浏览器中。

现在,我想要另一个下载PNG文件的选项。这是我尝试过的:

// this action displays a QR code in the browser
public function qrgen() {
    $this->layout = false;
    $this->response->type('image/png');
}

// this action SHOULD make the png download
public function download_qrgen() {
    $qrUrl = Router::url(['controller'=>'events','action'=>'qrgen']);
    $this->response->file($qrUrl,['download'=>true,'name'=>'qr']);
    return $this->response;
}

// in the "qrgen" view
QRcode::png('example value',null,"M",4,4);

但是当我访问www.example.com/events/download_qrgen时,出现错误“找不到该页面”,并将CakeResponse->file(string,array)的值显示为:/var/www/example.com//events/qrgen

如果我尝试在Webroot中尝试下载文件,它将正确下载该文件。但是我似乎无法下载这样的动态生成的png。

解决方法

CakeResponse::file()需要传递给它的文件系统路径,而不是URL,它不会发出任何HTTP请求来获取数据。

您必须自己获取数据,然后将其缓冲在一个临时文件中,该文件的路径可以在文件系统中传递给CakeResponse::file()

public function download_qrgen() {
    $this->layout = false;
    $qrcodeData = $this->_getViewObject()->render('qrgen');

    $temp = tmpfile();
    fwrite($temp,$qrcodeData);
    $filePath = stream_get_meta_data($temp)['uri'];

    $this->response->file($filePath,['download' => true,'name' => 'qr.png']);

    return $this->response;
}

或者您自己准备包含数据和标头的响应:

public function download_qrgen() {
    $this->layout = false;
    $qrcodeData = $this->_getViewObject()->render('qrgen');

    $this->response->type('image/png');
    $this->response->download('qr.png');
    $this->response->length(strlen($qrcodeData));
    $this->response->header('Content-Transfer-Encoding','binary');
    $this->response->body($qrcodeData);

    return $this->response;
}

另请参见