使用Response::download在Laravel中下载文件

109
在Laravel应用程序中,我正在尝试在视图中实现一个按钮,允许用户下载文件而无需导航到任何其他视图或路由。 现在我有两个问题: (1) 下面的函数会抛出

The file "/public/download/info.pdf" does not exist

(2) 下载按钮不应该导航用户到任何地方,而是在同一个视图上直接下载文件。我的当前设置将视图路由到 '/download'。

这是我尝试实现的方式:

按钮:

  <a href="/download" class="btn btn-large pull-right"><i class="icon-download-alt"> </i> Download Brochure </a>

路由:

Route::get('/download', 'HomeController@getDownload');

控制器:

public function getDownload(){
        //PDF file is stored under project/public/download/info.pdf
        $file="./download/info.pdf";
        return Response::download($file);
}
12个回答

217

试试这个。

public function getDownload()
{
    //PDF file is stored under project/public/download/info.pdf
    $file= public_path(). "/download/info.pdf";

    $headers = array(
              'Content-Type: application/pdf',
            );

    return Response::download($file, 'filename.pdf', $headers);
}

"./download/info.pdf" 不起作用,因为您必须提供完整的物理路径。

更新 20/05/2016

Laravel 5、5.1、5.2 或 5.* 用户可以使用以下方法代替 Response 外观。然而,我的先前答案适用于 Laravel 4 或 5。($header 数组结构更改为关联数组 => - 删除 'Content-Type' 后面的冒号 - 如果不进行这些更改,则标题将以错误的方式添加:标题名称将以数字0、1、...开头)

$headers = [
              'Content-Type' => 'application/pdf',
           ];

return response()->download($file, 'filename.pdf', $headers);

1
有没有办法返回文件下载并更新视图? - Justin
我可以在下载时更改文件权限吗? @Anam - Eswara Reddy
@EswaraReddy,你是指实时转换吗?我觉得不太可能。 - Anam
@SazzadTusharKhan 你只需要更改 Content-type、文件名和文件路径即可实现。 - Anam
6
请使用return Response::download($pathToFile);来下载文件。 - Anam
显示剩余4条评论

53

Laravel 5 中的文件下载非常简单。正如@Ashwani所提到的,Laravel 5允许使用response()->download()进行文件下载,从而返回可下载的文件。我们不再需要操纵任何标题。我们只需要这样返回一个文件:

return response()->download(public_path('file_path/from_public_dir.pdf'));

从控制器内部开始。


可重复使用的下载路由/控制器

现在让我们创建一个可重复使用的文件下载路由和控制器,这样我们就可以提供 public/files 目录中的任何文件。

创建控制器:

php artisan make:controller --plain DownloadsController

app/Http/routes.php中创建路由:
Route::get('/download/{file}', 'DownloadsController@download');

app/Http/Controllers/DownloadsController 中创建下载方法:

class DownloadsController extends Controller
{
  public function download($file_name) {
    $file_path = public_path('files/'.$file_name);
    return response()->download($file_path);
  }
}

现在只需将文件放入public/files目录中,然后您可以通过链接到/download/filename.ext来提供服务:

<a href="/download/filename.ext">File Name</a> // update to your own "filename.ext"

如果你引入了Laravel Collective的Html包,你就可以使用Html外观:

{!! Html::link('download/filename.ext', 'File Name') !!}

运行得非常好,非常感谢@DutGRIFF,你救了我的一天。我尝试了5个小时的下载,但是没有成功,我没有得到任何解决方案,但是当我尝试了你的解决方案后,它运行得非常好。Laravel非常棒。 - Prasad Patel
这是完美的代码!运行得像魅力一样! - Faiyaj

30
在被接受的答案中,对于 Laravel 4,头部信息数组构造错误。使用以下代码:
$headers = array(
  'Content-Type' => 'application/pdf',
);

数组实例化的差异可能是由于PHP版本而不是Laravel版本;) - ShaneMit

11

有相当多的解决方案建议引用Laravel应用程序的public_path()方法来定位文件。有时您可能需要控制对文件的访问或提供实时监视文件。在这种情况下,您将希望保持目录私有,并通过控制器类中的方法限制访问。以下方法应该有助于解决这个问题:

public function show(Request $request, File $file) {

    // Perform validation/authentication/auditing logic on the request

    // Fire off any events or notifiations (if applicable)

    return response()->download(storage_path('app/' . $file->location));
}

除此之外,还有其他可用的路径,这些路径在Laravel帮助函数文档中有描述。


感谢您的贡献。我一直遇到 Http 500 错误,但这个方法对我的情况有效。 - Redgren Grumbholdt

8

在使用laravel 5时,使用以下代码即可,无需头文件。

return response()->download($pathToFile); .

如果您正在使用Fileentry,则可以使用以下函数进行下载。

// download file
public function download($fileId){  
    $entry = Fileentry::where('file_id', '=', $fileId)->firstOrFail();
    $pathToFile=storage_path()."/app/".$entry->filename;
    return response()->download($pathToFile);           
}

2
如果回答省略掉不必要的部分,或者在纯粹的答案下面进行扩展,那么这个答案会很有帮助。Fileentry是一个不需要的不同特性。编辑答案后我会点赞,因为它提到了LV5的response()->download() - DutGRIFF

8

HTML href 链接点击:

<a ="{{ route('download',$name->file) }}"> Download  </a>

在控制器中:
public function download($file){
    $file_path = public_path('uploads/cv/'.$file);
    return response()->download( $file_path);
}

在路由中:

Route::get('/download/{file}','Controller@download')->name('download');

8

我认为您可以使用

$file= public_path(). "/download/info.pdf";

$headers = array(
        'Content-Type: ' . mime_content_type( $file ),
    );

通过这样的方式,您可以确保文件是一个PDF。

3

// 尝试使用以下代码下载任何文件。 Laravel 5.*

// 您需要使用门面 "use Illuminate\Http\Response;"

public function getDownload()
{

//PDF file is stored under project/public/download/info.pdf

    $file= public_path(). "/download/info.pdf";   

    return response()->download($file);
}

2
 HTML link click 
<a class="download" href="{{route('project.download',$post->id)}}">DOWNLOAD</a>


// Route

Route::group(['middleware'=>['auth']], function(){
    Route::get('file-download/{id}', 'PostController@downloadproject')->name('project.download');
});

public function downloadproject($id) {

        $book_cover = Post::where('id', $id)->firstOrFail();
        $path = public_path(). '/storage/uploads/zip/'. $book_cover->zip;
        return response()->download($path, $book_cover
            ->original_filename, ['Content-Type' => $book_cover->mime]);

    }

0

你可以在控制器内简单地使用以下代码: return response()->download($filePath); 编码愉快 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接