メモ > 技術 > フレームワーク: Laravel > ファイル
ファイル
■ファイルの保存(ローカル)
ファイルストレージ 5.5 Laravel
https://readouble.com/laravel/5.5/ja/filesystem.html
コントローラなどで以下を読み込む
use Illuminate\Support\Facades\Storage;
以下のコードを実行すると
Storage::put('test/1.txt', 'test1');
以下にファイルが保存される。ファイル内には「test1」と書き込まれる
storage\app\test\1.txt
■ファイルの保存(S3)
Laravel 5.4でS3ファイルアップロード - Qiita
https://qiita.com/zz22394/items/cd960124c3aec164a24d
ファイルのアップロード - ララジャパン
http://www.larajapan.com/tag/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%82%A2%E3%83%83%E3%83%9...
あらかじめAWSのコンソールで、S3のバケットを作成しておく
ドライバをインストール
composer require league/flysystem-aws-s3-v3
S3を使うために、.envに設定を追加する
AWS_KEY=XXXXX
AWS_SECRET=YYYYY
AWS_REGION=ap-northeast-1
AWS_BUCKET=laravel-test
コントローラなどで以下を読み込む
use Illuminate\Support\Facades\Storage;
以下のコードを実行するとアップロードされる
Storage::disk('s3')->put('test/1.txt', 'test1', 'public');
AWSのコンソールで、ファイルが作成されていることを確認する
なお、以下のようにしてアップロードするようにしておくと、
.env に「FILESYSTEM_CLOUD=public」を追加することで「ローカル環境の場合のみS3を使用しない」などができるようになる
(ローカル環境なら storage\app\public\test に保存されるようになる)
$image = $request->file('image')->storeAs(
'test', 'image.jpg', config('filesystems.cloud')
);
■ファイルアップロード
一例だが、以下のようなフォームからアップロードできる
<input type="file" id="image" name="image">
@if (isset($information) && $information->image)
<label>
<input type="checkbox" id="image_delete" name="image_delete" value="{{{ $information->image }}}"> ファイルを削除する
</label>
@endif
@if ($errors->first('image'))
<span class="help-block">
<strong>{{ $errors->first('image') }}</strong>
</span>
@endif
サービスで受け取って以下のように処理する
いったん一時的なディレクトリに保存し、データベースを更新できたら正式な場所に移動させている
public function postInformation($id, InformationCreateRequest $request)
{
$input = $request->only([
'title',
'body',
'datetime',
]);
$temporary_directory = 'temp/' . $request->session()->getId() . '/';
$extension = pathinfo($request->file('image')->getClientOriginalName(), PATHINFO_EXTENSION);
$file_path = $request->file('image')->storeAs($temporary_directory, 'image.' . $extension, config('filesystems.cloud'));
$input['image'] = basename($file_path);
try {
return DB::transaction(function () use ($id, $input, $temporary_directory) {
$result = $this->informationRepository->save($id, $input);
$data_directory = 'information/' . $result->id . '/';
if (isset($input['image_delete'])) {
Storage::disk(config('filesystems.cloud'))->delete($data_directory . $input['image_delete']);
} elseif (isset($input['image'])) {
Storage::disk(config('filesystems.cloud'))->delete($data_directory . $input['image']);
Storage::disk(config('filesystems.cloud'))->move($temporary_directory . $input['image'], $data_directory . $input['image']);
Storage::disk(config('filesystems.cloud'))->setVisibility($data_directory . $input['image'], 'public');
}
Storage::disk(config('filesystems.cloud'))->deleteDirectory($temporary_directory);
});
} catch (\Exception $e) {
return null;
}
}
InformationCreateRequest では以下のようにして入力チェックできる
public function rules()
{
return [
'title' => 'required|string|max:191',
'body' => 'required|string|max:1000',
'datetime' => 'required|date',
'image' => 'nullable|mimes:jpeg,gif,png|max:1000',
];
}
ビューで以下のようにすることで、ファイルを表示できる
@if ($information->image)
<img src="{{ Storage::disk(config('filesystems.cloud'))->url('information/' . $information->id . '/' . $information->image) }}">
@endif
S3使用時でも、ローカル環境で .env に以下を追記することで、storage\app\public\ 内にファイルが保存される
FILESYSTEM_CLOUD=public
ローカルに保存する場合、以下のコマンドを実行すると storage\app\public\ 内のファイルを /storage/ で参照できるようになる
(シンボリックリンクが張られる)
$ php artisan storage:link
The [public/storage] directory has been linked.
homestead - Laravel 5.3 storage:link -> symlink(): Protocol error - Stack Overflow
https://stackoverflow.com/questions/39496598/laravel-5-3-storagelink-symlink-protocol-error
PHP - Laravel5.4で画像をアップロードし、public/imagesに保存したい|teratail
https://teratail.com/questions/89984
Laravelで画像ファイルアップロードをする簡単なサンプル - Qiita
http://qiita.com/makies/items/0684dad04a6008891d0d
Laravel上画像アップロード - Qiita
http://qiita.com/samudra/items/3cb97bd6f1750c3f8134
■ファイルアップロード(保存先が異なる場合の補足)
デフォルトで storage/app/public が参照されるが、
例えば storage/app 直下に products などを作って保存する場合には問題がある
この場合、以下のように手動でシンボリックリンクを作成するといい
# rm /var/www/public/storage
# ln -s /var/www/storage/app /var/www/public/storage
laravel - Laravel-ローカルストレージのシンボリックリンクを元に戻して更新する方法
https://www.webdevqa.jp.net/ja/laravel/laravel%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%82%B9%E3%83%88...
■ファイルアップロード(Docker環境での補足)
PHPのコンテナ内で、通常どおり以下を実行すると対応できる
# php artisan storage:link
■ファイルアップロード(Vagrant環境での補足)
$ php artisan storage:link
In Filesystem.php line 228:
symlink(): Protocol error
このようなエラーになる場合、いったん
>vagrant halt
でHomesteadを終了し、コマンドプロンプトを右クリックして「管理者として実行」で起動する
その状態で再度以下を実行する
$ php artisan storage:link
それでも解決しなければ、Windowsのコマンドプロンプトから以下のように実行する
ショートカットのようなものが作成されるが、これはシンボリックリンク
(コマンドプロンプトは管理者権限で起動しないと、「この操作を実行するための十分な特権がありません。」のエラーになるので注意)
>cd C:\Vagrant\test\code\main\public
>mkdir storage
>cd storage
>mklink /D gift_item ..\..\storage\app\gift_item
gift_item <<===>> ..\..\storage\app\gift_item のシンボリック リンクが作成されました
WindowsでLaravelのphp artisan storage:linkが実行できなかった場合の対処法 - Qiita
https://qiita.com/shioharu_/items/608d024c48d9d9b5604f
コマンドプロンプト | シンボリックリンクの作成(MKLINK)
https://www.javadrive.jp/command/dir/index8.html
■CSSファイルやJSファイルのパスに、自動でファイルのタイムスタンプを追加する
LaravelでBladeを拡張する(@asset( )) - Qiita
https://qiita.com/reflet/items/a24b3c8e809f75fdbc19
実際は、以下のようにして組み込んだ
app\Providers\BladeServiceProvider.php を作成
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Blade;
class BladeServiceProvider extends ServiceProvider
{
/**
* Bladeサービスの初期化処理
*
* @return void
*/
public function boot()
{
/**
* CSSファイルやJSファイルのパスに、ファイルのタイムスタンプを追加
*
* @param string $file
* @return string
*/
Blade::directive('asset', function ($file) {
$file = str_replace(["'", '"'], '', $file);
$path = public_path() . '/' . $file;
try {
$timestamp = "?<?php echo \File::lastModified('{$path}') ?>";
} catch (\Exception $e) {
$timestamp = '';
}
return asset($file) . $timestamp;
/*
// ロードバランサーを考慮する場合(環境によってはURLを自動取得できないので、.envのAPP_URLを参照)
$app_url = env('APP_URL');
if (empty($app_url)) {
return asset($file) . $timestamp;
} else {
return $app_url . '/' . $file . $timestamp;
}
*/
});
}
/**
* アプリケーションサービスの登録
*
* @return void
*/
public function register()
{
//
}
}
config\app.php を編集
'providers' => [
〜略〜
App\Providers\BladeServiceProvider::class,
ビュー内で以下のように asset を使用すると、ファイル名の最後に「?1541565515」のような値が追加される
<script src="@asset('js/app.js')"></script>
<script src="@asset('js/plugins/datetimepicker/jquery.datetimepicker.full.min.js')"></script>