Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用指向外部资源的URL在Laravel中下载文件_Php_Laravel - Fatal编程技术网

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

Php 使用指向外部资源的URL在Laravel中下载文件,php,laravel,Php,Laravel,我将所有上传内容保存在一个自定义的外部驱动器上。这些文件是通过自定义API存储的 在Laravel 5.2中,我可以对本地文件执行以下操作以下载它: return response()->download('path/to/file/image.jpg'); 不幸的是,当我传递URL而不是路径时,Laravel会抛出一个错误: 文件“”不存在 (当然,URL是一个虚拟的) 有什么方法可以使用Laravel的实现下载image.jpg文件,还是使用普通PHP来下载?为什么不使用简单的重定向

我将所有上传内容保存在一个自定义的外部驱动器上。这些文件是通过自定义API存储的

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

return response()->download('path/to/file/image.jpg');
不幸的是,当我传递URL而不是路径时,Laravel会抛出一个错误:

文件“”不存在

(当然,URL是一个虚拟的)


有什么方法可以使用Laravel的实现下载image.jpg文件,还是使用普通PHP来下载?

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

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

您可以下拉原始文件的内容,计算出其mime类型,然后根据正确的头创建自己的响应

我自己使用PDF库来实现这一点,但您可以修改为使用
file\u get\u 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
更改为文件的数据,
内容类型
包含数据所在文件的mimetype,
内容配置
是您希望其显示为的文件名


不确定这是否会起作用,我的只是让浏览器弹出一个PDF下载,所以我不确定它是否能嵌入CDN文件。。。不过值得一试。

没有魔法,您应该使用函数下载外部图像,然后在响应中将其发送给用户:

$filename='temp image.jpg';
$tempImage=tempnam(sys_get_temp_dir(),$filename);
复制('https://my-cdn.com/files/image.jpg“,$tempImage);
return response()->下载($tempImage,$filename);
试试这个脚本:

// $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);
如果不希望最终用户可以在标题中看到主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);

TL;DR
如果使用5.6或更高版本,请使用。否则,请执行以下功能

原始答案
与“下载”响应非常相似,Laravel有一个“流”响应,可用于执行此操作。看看,这两个函数都是围绕Symfony的BinaryFileResponse和StreamdResponse类的包装。在Symfony文档中,他们有很好的

下面是我使用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;
});

至于2020年,这一切都很容易

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

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

//将文件内容加载到变量中。
$contents=file_get_contents('www.google.com');
//将变量另存为`google.html`文件
//您的本地驱动器,很可能位于'your_laravel_project/storage/app/`
//路径(根据默认的Laravel存储配置)
存储::磁盘('local')->put('google.html',$contents);
//--在这里,您已经从URL保存了文件
//--到服务器上的本地Laravel存储文件夹。
//--默认情况下,这是'your laravel project/storage/app'文件夹。
//现在,如果需要,如果您在web应用程序的
//HTTP请求(与CLI应用程序相反)
//文件可以随响应一起发送到浏览器(客户端)
//指示浏览器在客户端下载文件的:
//获取本地文件系统中的文件路径
$path=Storage::url('google.html');
//向启动文件downolad的客户端返回HTTP响应
return response()->download($path、$name、$headers);

请查阅Laravel文档,了解有关磁盘配置的详细信息,以及使用HTTP响应返回文件的方法和文档。

可能重复@Jamesking56 Nah,首先,您链接的帖子是关于S3的,Laravel支持S3作为可能的远程磁盘(所以不是我的情况)。第二,即使帖子是类似的,也基本上没有答案。这将重定向到外部资源-并停留在页面上,这绝对不是我需要的;)我的另一个问题是关于下载远程URL。不是本地文件。实际上这个问题很模糊。文本描述假定文件下载到服务器。代码片段建议需要将带有HTTP响应的文件上载到浏览器(这反过来假设文件存在于服务器的文件系统中,因此它已经从URL下载)@詹姆斯金56在第二部分是对的。为什么要向下投票。@Artistan注意我回答中的一行“但是你可以修改使用file\u get\u contents()来下拉远程资产”你的方法比
copy()
好得多,特别是当它是一个像视频下载这样的大文件时。这会导致php内存不足。从错误中看,它似乎试图将整个文件加载到内存中,我在内存中执行
echo file\u get\u contents…
@JonMcClung是的,你是对的。在上面的示例中,“echo file\u get\u contents”将整个文件拉入内存。我这样做只是为了保持示例的简单性。我想如果你想真正流式传输文件,你必须像这样传递流式上下文,这里是流式上下文的文档,你可以用
readfile
而不是
file\u get\u contents
?对的回答似乎表明,
readfile
返回一个流,在流式传输响应时,这可能会执行得更好?@Dwight yes我刚才使用了
readfile($url)并且它可以工作。我认为这就像
标题(“内容配置:附件;文件名=$name”);标题(“内容类型:应用程序/下载”);readfile($url)
复制的文件是通过垃圾收集删除的,还是应该自己取消链接?如果是这样的话,我们在这里返回响应时如何执行此操作?我现在看到,在某个时候,Laravel向下载响应添加了一个
->deleteFileAfterSend()
方法。我需要做什么?如果我在我的服务器位置添加永久文件?
<?php

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