PHP Laravel:實作下載檔案的方法

Table of Contents

Table of Contents

從Laravel中下載檔案

在很多做管理介面的網站中,特別是分析數據、儲存資料的服務等,常常會看到有下載檔案的選項,讓使用者可以去取得想要的資料到自己的電腦。
Laravel也因應這樣的作業需求,提供了下載儲存在伺服器端的檔案、圖片或是從資料庫中取得資料轉成文字檔案輸出的方法。
接下來將討論其中常用到的作法,以及將Array的內容做成csv檔案後輸出。

教學影片

處理流程

  • 準備下載處理的Controller: ExportController
  • 兩種檔案下載方法:
    • 方法1: Storage::download()
    • 方法2: response()->download()
  • 將Array的內容製作csv檔案後下載: response()->stream()

ExportController & web

先準備ExportController,裡面備有download_storagedownload_response兩個函數,稍後會在這兩個函數中分別使用Storage::download()response()->download()方法。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class ExportController extends Controller
{

    public function download_storage(Request $request)
    {
        //...
    }

    public function download_response(Request $request)
    {
        //...
    }

}

web.php中設定好路徑。


Route::get('/export/download_storage', [ExportController::class, 'download_storage'])->name('export.download_storage');
Route::get('/export/download_response', [ExportController::class, 'download_response'])->name('export.download_response');

方法1 Storage::download($filePath, $fileName, $headers)

在Laravel專案的根目錄下,storage/app/public的路徑中準備一份test.png的圖片檔案。
然後使用Storage::download()方法下載圖片檔案。

public function download_storage(Request $request)
{
    $filePath = 'public/test.png';
    $fileName = 'test.png';
    $mimeType = Storage::mimeType($filePath);
    $headers = [['Content-Type' => $mimeType]];
    return Storage::download($filePath, $fileName, $headers);
}

方法2 response()->download($filePath, $fileName, $headers)

一樣,在Laravel專案的根目錄下,storage/app/public的路徑中準備好test.png的圖片檔案。
response()->download()方法取得檔案後下載。

public function download_response(Request $request)
{
    $filePath = Storage::path('public/test.png');
    $fileName = 'test.png';
    $mimeType = Storage::mimeType($filePath);
    $headers = [['Content-Type' => $mimeType]];
    return response()->download($filePath, $fileName, $headers);
}

將Array的內容做成csv檔案

這裡使用response()->stream()方法,在callback中用fopen()fputcsv()來製作csv檔案。

public function csv_stream(Request $request)
{
    $response_headers = [
            'Content-type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename=export.csv',
            'Pragma' => 'no-cache',
            'Expires' => 0,
        ];
        
        $results = [
            ['id', 'name', 'class'],
            [1, 'John', '1-A'],
            [2, 'Tom', '1-B'],
            [3, 'Mary', '2-A'],
            [4, 'May', '2-B'],
        ];
        $callback = function () use ($results) {
            $resource = fopen('php://output', 'w');
            foreach ($results as $row) {
                fputcsv($resource, $row);
            }
            fclose($resource);
        };
        return response()->stream($callback, 200, $response_headers);
}

最後記得在web.php加入route。

Route::get('/export/csv_stream', [ExportController::class, 'csv_stream'])->name('export.csv_stream');