使用外部资源的URL在Laravel中下载文件

时间:2016-08-05 14:25:59

标签: php laravel

我将所有上传内容保存在自定义外置硬盘上。这些文件是通过自定义API存储的。

在Laravel 5.2中,我可以为本地文件执行此操作以下载它:

return response()->download('path/to/file/image.jpg');

不幸的是,当我传递URL而不是路径时,Laravel会抛出错误:

  

文件“https://my-cdn.com/files/image.jpg”不存在

(当然,URL是虚拟的)。

有没有办法可以使用Laravel的实现下载 image.jpg 文件,还是用普通的PHP代替?

6 个答案:

答案 0 :(得分:24)

没有魔力,您应该使用copy()功能下载外部图像,然后在响应中将其发送给用户:

$filename = 'temp-image.jpg';
$tempImage = tempnam(sys_get_temp_dir(), $filename);
copy('https://my-cdn.com/files/image.jpg', $tempImage);

return response()->download($tempImage, $filename);

答案 1 :(得分:14)

<强> TL; DR
如果您使用的是5.6&gt; =,请使用streamDownload response。否则执行以下功能。

原始答案
非常类似于&#34;下载&#34;回应,Laravel有一个&#34; stream&#34;可用于执行此操作的响应。查看API,这两个函数都是Symfony的BinaryFileResponse和StreamedResponse类的包装器。在Symfony文档中,他们有很好的examples of how to create a StreamedResponse

以下是使用Laravel的实现:

<?php

use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;

Route::get('/', function () {
    $response = response()->stream(function () {
        echo file_get_contents('http://google.co.uk');
    });

    $name = 'index.html';

    $disposition = $response->headers->makeDisposition(
        ResponseHeaderBag::DISPOSITION_ATTACHMENT,
        $name,
        str_replace('%', '', Str::ascii($name))
    );

    $response->headers->set('Content-Disposition', $disposition);

    return $response;
});

更新2018-01-17

现在已merged into Laravel 5.6,已添加到5.6 docs。 streamDownload响应可以像这样调用:

<?php

Route::get('/', function () {
    return response()->streamDownload(function () {
        echo file_get_contents('https://my.remote.com/file/store-12345.jpg');
    }, 'nice-name.jpg');
});

答案 2 :(得分:7)

为什么不使用简单的重定向?

return \Redirect::to('https://my-cdn.com/files/image.jpg');

答案 3 :(得分:2)

试试这个脚本:

// $main_url is path(url) to your remote file
$main_url = "http://dl.aviny.com/voice/marsieh/moharram/92/shab-02/mirdamad/mirdamad-m92-sh2-01.mp3";
header("Content-disposition:attachment; filename=$main_url");
readfile($main_url);

如果您不希望最终用户在标题中看到main_url,请尝试以下操作:

$main_url = "http://dl.aviny.com/voice/marsieh/moharram/92/shab-02/mirdamad/mirdamad-m92-sh2-01.mp3";
$file = basename($main_url);
header("Content-disposition:attachment; filename=$file");
readfile($main_url);

答案 4 :(得分:2)

至于2019年,这一切都非常容易。

2行代码下载到您的服务器,2行代码上传到浏览器(如果需要)。

假设您希望将Google主页的HTML本地保存到服务器上,然后返回HTTP响应以启动浏览器以下载文件:

// Load the file contents into a variable.
$contents = file_get_contents('www.google.com');

// Save the variable as `google.html` file onto
// your local drive, most probably at `your_laravel_project/storage/app/` 
// path (as per default Laravel storage config)
Storage::disk('local')->put('google.html', $contents);

// -- Here your downloaded the file from URL 
// -- to your local Laravel storage (server).

// -- Now, if desired, and if you are doing this within a web application's
// -- HTTP request (as opposite to CLI application)
// -- the file can be sent to the browser (client) with the response
// -- to be downloaded at a browser side

// Get the file path within you local filesystem
$path = Storage::url('google.html');

// Return HTTP response to a client that initiates the file downolad
return response()->download($path, $name, $headers);

请查阅Laravel Storage facade文档以获取有关磁盘配置,put方法和Response with file download文档以获取带有HTTP响应的文件的详细信息。

答案 5 :(得分:-2)

你可以下拉原始文件的内容,计算出它的mime类型,然后制作你自己的响应,给出正确的标题。

我自己使用PDF库执行此操作,但您可以修改为使用file_get_contents()来下拉远程资源:

return Response::make(
        $pdf,
        200,
        array(
            'Content-Description' => 'File Transfer',
            'Cache-Control' => 'public, must-revalidate, max-age=0, no-transform',
            'Pragma' => 'public',
            'Expires' => 'Sat, 26 Jul 1997 05:00:00 GMT',
            'Last-Modified' => ''.gmdate('D, d M Y H:i:s').' GMT',
            'Content-Type' => 'application/pdf', false,
            'Content-Disposition' => ' attachment; filename="chart.pdf";',
            'Content-Transfer-Encoding' => ' binary',
            'Content-Length' => ' '.strlen($pdf),
            'Access-Control-Allow-Origin' => $origin,
            'Access-Control-Allow-Methods' =>'GET, PUT, POST, DELETE, HEAD, PATCH',
            'Access-Control-Allow-Headers' =>'accept, origin, content-type',
            'Access-Control-Allow-Credentials' => 'true')
        );

您需要将$pdf更改为文件的数据Content-Type,以包含数据所在文件的mimetype,Content-Disposition是您希望其显示的文件名如

不确定这是否会起作用,我只是简单地使浏览器弹出PDF下载所以我不确定它是否适用于嵌入CDN文件......值得一试。