日本語ファイルがダウンロードできない
Laravelには便利なアクションがあって、以下のようなコードで簡単にファイルをダウンロードさせられるのだが 何かのコントローラの何かのアクション
public function test(Request $request) { $filePath = '/var/www/hogehoge.zip'; return response()->download($filePath); }
以下だとThe filename fallback must only contain ASCII charactersと怒られてしまう。 何かのコントローラの何かのアクション
public function test(Request $request) { $filePath = '/var/www/ほげほげ.zip'; return response()->download($filePath); // InvalidArgumentException }
これは内部で利用しているSymfonyのコンポーネントが引数をASCIIで受け取ることを前提としているせい。
どうすればいいのか
ちょっと前のLaravelであれば、訂正版:Laravelのエラー「The filename fallback must only contain ASCII characters」の対処法のようにして対応することができる。
しかし、Laravel 5.1ではマクロ周りの仕様が変わっており、このまま対応することはできない。
というわけで、5.1の仕様に則した方法をメモ。
まず、app\Providersあたりに”ResponseMacroServiceProvider”としてサービスプロバイダを作成。(別にプロバイダの名前はなんでもいい)
あとはおもむろに以下のように書く。 ResponseMacroServiceProvider.php
namespace App\Providers; // 名前空間を変更しているなら適宜直しましょう use Illuminate\Support\Str; use Illuminate\Support\ServiceProvider; use Illuminate\Contracts\Routing\ResponseFactory; use Symfony\Component\HttpFoundation\BinaryFileResponse; class ResponseMacroServiceProvider extends ServiceProvider { public function boot(ResponseFactory $factory) { // ここではdownloadExとして登録していますが、何でも良いです $factory->macro('downloadEx', function($file, $name = null, array $headers = array(), $disposition = 'attachment'){ $response = new BinaryFileResponse($file, 200, $headers, true); if (is_null($name)) { $name = basename($file); } return $response->setContentDisposition($disposition, $name, Str::ascii($name)); }); } // registerは今回特に必要ないです /** * Register the service provider. * * @return void */ public function register() { // TODO: Implement register() method. } }
あとはconfig\app.phpにサービスプロバイダとして
ResponseMacroServiceProviderを追加。
app.php
return [ // ~省略~ 'providers' => [ // ~省略~ App\Providers\ResponseMacroServiceProvider::class, ]; // ~省略 ~ ];
これで完了。あとは最初のコードをこんな感じにするだけ。 何かのコントローラの何かのアクション
public function test(Request $request) { $filePath = '/var/www/ほげほげ.zip'; return response()->downloadEx($filePath); // OK! }
簡単で今までよりも見通しがよくなりました。バンザイ!
Strage downloadだと全角ファイル名がダメそう
public function downloadFile(Request $request)
{
$disk = Storage::disk('s3');
// 1.ファイルの名前をURIや、リクエストなどで渡す
$file_name = $request->input('file_name')
// 2.アップロードしたいディレクトリのパス
$s3_dir_pash = 'upload/';
// 1と2をあわせて、アップロード先パスを指定
$s3_file_pash = $s3_dir_pash.$file_name; //'upload/5007.jpg'
// ダウンロードする際のファイル名を、Content-Dispositionで指定
$headers = [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment; filename="' . $file_name . '"'
];
return \Response::make($disk->get($s3_file_pash), 200, $headers);
//$disk->download($s3_file_pash, $file_name, $headers);
//↑の書き方でも良いが、日本語のファイル名でダウロードすると、The filename fallback must only contain ASCII characters.になってしまう。
}
fromURL:http://sagatto.com/20190130_laravel_s3_file_operation