php 使用外部资源的 URL 在 Laravel 中下载文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38791635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Download a file in Laravel using a URL to external resource
提问by lesssugar
I'm keeping all uploads on a custom, external drive. The files are being stored via custom API.
我将所有上传内容保存在自定义的外部驱动器上。文件通过自定义 API 存储。
In Laravel 5.2, I can do this for a local file to download it:
在 Laravel 5.2 中,我可以为本地文件执行此操作以下载它:
return response()->download('path/to/file/image.jpg');
Unfortunately, when I pass a URL instead of a path, Laravel throws an error:
不幸的是,当我传递一个 URL 而不是路径时,Laravel 会抛出一个错误:
The file "https://my-cdn.com/files/image.jpg" does not exist
(the URL is a dummy of course).
(当然,URL 是一个虚拟的)。
Is there any way I can download the image.jpgfile using Laravel's implementation or do I do this with plain PHP instead?
有什么方法可以使用 Laravel 的实现下载image.jpg文件,还是使用普通的 PHP 来下载?
回答by Limon Monte
There's no magic, you should download external image using copy()
function, then send it to user in the response:
没有魔法,您应该使用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);
回答by Theo Kouzelis
TL;DR
Use the streamDownload responseif you're using 5.6 <=. Otherwise implement the function below.
TL;DR如果您使用的是 5.6 <=,
请使用streamDownload 响应。否则实现下面的功能。
Original Answer
Very similar to the "download" response, Laravel has a "stream" response which can be used to do this. Looking at the API, both of the these functions are wrappers around Symfony's BinaryFileResponse and StreamedResponse classes. In the Symfony docs they have good examples of how to create a StreamedResponse
原始答案
与“下载”响应非常相似,Laravel 有一个“流”响应可用于执行此操作。查看API,这两个函数都是围绕 Symfony 的 BinaryFileResponse 和 StreamedResponse 类的包装器。在 Symfony 文档中,他们有很好的示例说明如何创建 StreamedResponse
Below is my implementation using Laravel:
下面是我使用 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;
});
Update 2018-01-17
更新 2018-01-17
This has now been merged into Laravel 5.6and has been added to the 5.6 docs. The streamDownload response can be called like this:
这现已合并到 Laravel 5.6并已添加到5.6 文档中。streamDownload 响应可以这样调用:
<?php
Route::get('/', function () {
return response()->streamDownload(function () {
echo file_get_contents('https://my.remote.com/file/store-12345.jpg');
}, 'nice-name.jpg');
});
回答by Valentine Shi
As for 2019 this is all pretty easy.
至于 2019 年,这一切都很容易。
2 lines of code to download to your server and 2 lines to upload to browser (if needed).
2 行代码下载到您的服务器,2 行代码上传到浏览器(如果需要)。
Assume you want an HTML for google home page to get saved locally onto your server, and then return an HTTP response to initiate browser to download the file:
假设您希望将 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);
Look up Laravel Storage facadedocumentation for details on disk configuration and put
method and Response with file downloaddocumentaion for returning file with an HTTP reponse.
查找 Laravel存储外观文档以获取有关磁盘配置和put
方法的详细信息,以及使用文件下载文档的响应以返回带有 HTTP 响应的文件。
回答by Jamesking56
Why not just use a simple redirect?
为什么不使用简单的重定向?
return \Redirect::to('https://my-cdn.com/files/image.jpg');
回答by masood
try this script:
试试这个脚本:
// $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);
If you do not want end user can see main_url in header try this:
如果您不希望最终用户可以在标题中看到 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);
回答by Jamesking56
You could pull down the content of the original file, work out its mime type and then craft your own response giving the right headers.
您可以下拉原始文件的内容,计算出它的 MIME 类型,然后制作您自己的响应并给出正确的标题。
I do this myself using a PDF library, but you could modify to use file_get_contents()
to pull down the remote assets:
我自己使用 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')
);
You need to change $pdf
to be the data of the file, Content-Type
to contain the mimetype of the file that the data is and Content-Disposition
is the filename you want it to appear as.
您需要更改$pdf
为文件的数据,Content-Type
以包含数据所在的文件的 mimetype,并且Content-Disposition
是您希望它显示为的文件名。
Not sure whether this will work, mine simply makes the browser popup with a PDF download so I'm not sure whether it'll work for embedding CDN files... Worth a try though.
不确定这是否有效,我的只是让浏览器弹出并下载 PDF,所以我不确定它是否适用于嵌入 CDN 文件......不过值得一试。