Laravel でファイル・ディレクトリをダウンロードする方法まとめ - inokawablog

    Laravel でファイル・ディレクトリをダウンロードする方法まとめ

    laravel と vue.js を使ってファイルをダウンロードする方法を紹介します。

     

    これらのファイル・ディレクトリダウンロード方法をまとめてあります。

    • aタグでダウンロード
    • Laravelでの標準的なファイルダウンロードの方法
    • Storageから直接ダウンロード
    • Response::make
    • zipファイルとしてダウンロード

     

    laravelとvue.jsを使ってファイルをダウンロードする

    aタグでダウンロード

    これは、laravelの機能を使ったものではありません。download属性を付けてリンクを作ってあげればダウンロードできます。

    <a href="./image.png" download="hoge.png">download</a>

    download属性 

     

    Laravelでの標準的なファイルダウンロードの方法

    Laravelでの標準的なファイルダウンロードの実装方法は、downloadメソッドが使用されます。downloadメソッドは指定したパスのファイルをダウンロードするようにブラウザに強要するレスポンスを生成するために使用します。

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

     

    Storageから直接ダウンロード

    return Storage::download('file.jpg');
    return Storage::download('file.jpg', $name, $headers);

    Downloading Files

     

    Response::make

    Response::makeでもできるみたいです。こちらはあまり使わないと思います。

    public function download(Request $request){
        $filename = 'sample.csv';
        $csv = '';//csvのデータ
        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="sample.csv"',
        ]; 
        return response()->make($csv, 200, $headers);
    }

     

    zipファイルとしてダウンロード

    laravel & vue.js でやっている場合を想定して紹介します。

    Zipperと言うライブラリを使用して簡単にファイル・ディレクトリをzipファイルをしてダウンロードできます。

    今回は /storage/app/files/sample.php と言うファイルを作成して、zip(sample.zip)にしてダウンロードするサンプルです。

    まずcomposerでZipperをインストールします。

    composer require chumper/zipper

    次に、config/app.phpに以下を追加して下さい。

    'providers' => [
        ....
        Chumper\Zipper\ZipperServiceProvider::class
    ],
    'aliases' => [
        ....
        'Zipper' => Chumper\Zipper\Zipper::class
    ]

     

    Sample.vue

    <template>
      <p v-on:click="generate">get file</p>
    </template>
    data: function () {
      return {
        sample: 'data',
      }
    },
    methods: {
      async generate () {
        try {
          const base_path = await axios.post('/base_url_get_path')
          const url = new URL(base_path.data + '/file_get_path');
          const params = url.searchParams;
          params.append('sample', this.data);
    
          window.location = url.href
        }catch (error) {
          const {status,statusText} = error.response;
          console.log(`Error! HTTP Status: ${status} ${statusText}`);
        }
      }
    },

     

    new URLはURL オブジェクトを生成するための静的なメソッドを提供するオブジェクトで、appendでパラメーターを付与します。

    window.location = url.href 出ないと、ダウンローできませんでした。axiosでgetしてもダウンロードできませんでした。

     

    routes/web.phpに以下を追記してください。

    web.php

    Route::post('/base_url_get_path', 'DownloadController@basePath');
    Route::get('/generate', 'DownloadController@generate');

     

    DownloadController.php

    <?php
    namespace App\Http\Controllers;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Storage;
    use Zipper;
    
    class DownloadController extends Controller
    {
          public function generate(Request $request)
          {
            $item = $request->all();
            $directory =  '/files';
            //ディレクトリ作成
            $directory_result = Storage::disk('local')->makeDirectory($directory);
            if ($directory_result) {
              //ファイルの内容
              $file_contents = '<?php echo "sample"; ?>'
              //サンプルファイルの作成
              $file_written = Storage::disk('local')->put($directory . '/sample.php', $file_contents);
              $download_path = $this->download($directory);
              if (!empty($download_path)) {
                //ファイルをダウンロード
                return response()->download($download_path)->deleteFileAfterSend(true);
              }else {
                return false;
              }
            }
          }
    
          private function download($directory)
          {
            if (Storage::disk('local')->exists('sample.zip')) Storage::disk('local')->delete('sample.zip');
            Zipper::make($zip_path)->add(storage_path('app' . $directory))->close();
            return storage_path('app/sample.zip');
          }
    
          public function basePath()
          {
            return url('/');
          }
    }

    一つずつ見ていきます

    $item = $request->all();

    フロント側からurlに付与したパラメータを取得しています。パラメーターによってファイル内容変更する場合もあると思うので入れておきました。zipだけ行いたい場合は必要ありません。

     

    $directory = '/files';
    
    $directory_result = Storage::disk('local')->makeDirectory($directory);

    /storage/app/filesを作成します。

     

    $file_contents = '<?php echo "sample"; ?>'
    $file_written = Storage::disk('local')->put($directory . '/sample.php', $file_contents);

    $file_contentsの内容で$directory . ‘/sample.php’に書き込みます。putはファイルがない場合には新規作成されます。

     

    private function download($directory)
    {
      if (Storage::disk('local')->exists('sample.zip')) Storage::disk('local')->delete('sample.zip');
      $zip_path = storage_path('app/sample.zip');
      Zipper::make($zip_path)->add(storage_path('app' . $directory))->close();
      return $zip_path;
    }

    すでに/strage/app/sample.zipがあったら削除します。

    ‘app’ . $directory に storage_path(‘app/sample.zip’) を作成します。close はzipを閉じて、すべての変更を書き込む処理です。

     

    return response()->download($download_path)->deleteFileAfterSend(true);

    $download_path にあるファイルをダウンロードします。deleteFileAfterSend はダウンロード後にファイルを削除するかどうかの設定です。

     

     

    これで以上になります。