i have a form with slug, input files, etc.
I need if i put por example in form:
slug = hello-how-are-you
file = header.png
file2 = home.png
Laravel create me a folder in storage like this: /projects/hello-how-are-you with the header.png and home.png.
I try it but can't do it.. i try with something like this:
public function storeProject(Request $request)
{
$project = new Project();
$project->slug = $request->input("slug");
$namefolder = $project->slug;
$project->position = $request->input("position");
$project->public = $request->input("public");
$header = $request->file('pathheader');
$home = $request->file('pathhome');
$project->pathheader = $header;
$project->pathhome = $home;
\Storage::disk('projects')->put('header.png', \File::get($header));
$project->save();
}
In filesystem i have this:
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
'projects' => [
'driver' => 'local',
'root' => storage_path() . '/projects',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_KEY'),
'secret' => env('AWS_SECRET'),
'region' => env('AWS_REGION'),
'bucket' => env('AWS_BUCKET'),
],
],
SOLVED!
Thanks to #Dees040
If want smash the name of the file and do it without a foreach, you can do it like this:
public function storeProject(Request $request)
{
$project = new Project();
$project->slug = $request->input("slug");
$project->position = $request->input("position");
$project->public = $request->input("public");
$project->pathheader = $request->file('pathheader');
$project->pathhome = $request->file('pathhome');
\Storage::disk('projects')->makeDirectory($project->slug);
\Storage::disk('projects')->putFileAs($project->slug,$project->pathheader,'header.png');
\Storage::disk('projects')->putFileAs($project->slug,$project->pathhome,'home.png');
$project->save();
}
This might do the trick for you:
public function storeProject(Request $request)
{
$project = Project::create($request->only('slug', 'position', 'public', 'pathheader', 'pathhome'));
\Storage::disk('projects')->makeDirectory($project->slug);
foreach ($request->allFiles() as $file) {
\Storage::disk('projects')->putFileAs($project->slug, $file, $file->getClientOriginalName());
}
}
Create the directory first:
use Illuminate\Support\Facades\Storage;
Storage::disk('projects')->makeDirectory($namefolder);
And then, store the files:
$project->pathheader = Storage::disk('projects')->putFileAs($namefolder, $header, $header->getClientOriginalName());
$project->pathhome = Storage::disk('projects')->putFileAs($namefolder, $home, $home->getClientOriginalName());
Related
I'm creating logic about uploading avatars to users:
blade.php
<image src="{{ $user->profile->image ? storage_path() . '/ app/public/' . $user->profile->image : '' }}"/>
<input type="file" id="avatar" name="avatar" style="display:none;"/>
<label for="avatar">{{ __('text.select_file') }}</label>
Controller (update method):
public function update(User $user)
{
$this->authorize('update', $user->profile);
$data = request()->validate([
'name' => 'required',
]);
if (request('avatar')) {
$imagePath = request('avatar')->store('uploads/avatars', 'public');
$image = Image::make(storage_path("app/public/{$imagePath}"))->fit(800, 800);
$image->save();
$imageArray = ['image' => $imagePath];
}
auth()->user()->profile->update(array_merge(
$data,
$imageArray ?? []
));
return redirect("/profile/{$user->id}");
}
When I upload a picture it is stored in storage/app/public/uploads/avatars in DB value for avatar is uploads/avatars/name.jpeg
As you can see I have hard code app/public/ in controller and in view files, this is by default, I didn't change any paths, here is filesystem.php:
<?php
return [
'default' => env('FILESYSTEM_DRIVER', 'local'),
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
],
],
'links' => [
public_path('storage') => storage_path('app/public'),
],
];
So how do I avoid these coded paths? And why Laravel default store folder is in storage and not in public directory ? Should I upload avatars to public directory or to leave them in storage? I'm looking for best and correct practices ?
I'm not well versed in Laravel, but I think you should be storing everything publicly accessible in /public/ with public_path(): Difference between storing files in public directory and in storage in Laravel 5.4
Just calling public_path($user->profile->image) should work, but you'll probably want to keep some path in there to make sure the avatars are in their own directory. Perhaps you could write another helper function:
function avatar_path($filename){
return public_path('avatars/'.$filename);
}
Then use avatar_path() everywhere rather than storage_path()/public_path(). I'm not sure if something as straightforward as that is the "Laravel way" though.
I upload my project in the host. I uploaded an image, and the image save in database. And the image did not show well, but it show in my localhost as well.
config/filesystem.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
],
],
web.php
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Route;
Auth::routes();
Route::get('/link', function(){
return Artisan::call('storage:link');
});
It return show 0.
Controller
public function update(Request $request)
{
$user = auth()->user();
$path = $user->image ?? null;
if ($request->hasFile('image'))
{
$file = $request->file('image');
$nane = time();
$extension = $file->getClientOriginalExtension();
$fileName = $nane . '.' . $extension;
$path = $file->storeAs('images/users', $fileName, 'public');
}
$user->image = $path;
}
The image save in database.
The image uploaded in storage/app/public/images/users folder.
The image did not uploaded public/images/users.
Then I change this
$path = Storage::disk('public')->store('images/users/'.$fileName);
I get this code
Storage facade
//Will store the uploaded image in /storage/app/public/images/users
$path = Storage::disk('public')->putFileAs('images/users', $file, $fileName);
Laravel docs: https://laravel.com/docs/8.x/filesystem#storing-files
UploadedFile
//Will store the uploaded image in /storage/app/public/images/users
$path = $request->image->storeAs('images/users', $filename, 'public');
Laravel docs: https://laravel.com/docs/8.x/requests#storing-uploaded-files
Little refactor for the update method
public function update(Request $request)
{
$user = auth()->user();
if ($request->hasFile('image') && $request->file('image')->isValid())
{
$file = $request->file('image');
$nane = time();
$extension = $file->getClientOriginalExtension();
$fileName = $nane . '.' . $extension;
$user->image = $file->storeAs('images/users', $fileName, 'public');
}
$user->save();
}
I can't display my images in a tag img in my view. I can save my uploaded image in storage->app->public->books and save the image name in my database as well. But after I run php artisan storage:link to access my file in public->storage, but whatever if I user asset() or url() method, I can't display my images in img tag, just alt="" atribute, Someone knows what I'm doing wrong?
This is my Controller store().
public function store(Request $request)
{
// Handle File Upload
if($request->hasFile('book_image')){
// Get filename with the extension
$filenameWithExt = $request->file('book_image')->getClientOriginalName();
// Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
// Get just ext
$extension = $request->file('book_image')->getClientOriginalExtension();
// Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
// Upload Image
$path = $request->file('book_image')->storeAs('books', $fileNameToStore);
} else {
$fileNameToStore = 'noimage.png';
}
//save in database
$itens = \App\Book::create([
'book_name' => mb_strtolower($request->book_name),
'author_name' => mb_strtolower($request->author_name),
'publishing_name' => mb_strtolower($request->publishing_name),
'description' => $request->description,
'release_date' => $request->release_date,
'category' => mb_strtolower($request->category),
'book_image' => $fileNameToStore
]);
flash('Livro criado com sucesso !')->success();
return redirect()->route('admin.books.index');
}
And this is my html where I'm trying to display.
#foreach($books as $book)
<tr>
<td><input type="checkbox" class="checkthis" /></td>
<td>
<img style="width: 80px;height: 80px" src="{{ url('books/{$book->book_image}') }}" alt="{{$book->book_image}}">
</td>
<td>{{$book->book_name}}</td>
<td>{{$book->author_name}}</td>
<td>{{$book->publishing_name}}</td>
<td>{{$book->release_date}}</td>
<td>
</tr>
And my config->filesystems.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
],
],
You need to pass src as below.
src="{{ url('books/'.$book->book_image) }}"
as storage folder
src="{{ asset('storage/books/'.$book->book_image) }}"
So I have a hidden input in my form where I set the name of old file
<input type="hidden" name="old_logo" value="{{ $company->logo }}">
And it is being set successfully:
<input type="hidden" name="old_logo" value="GsdRHGtbm950k6tegfuyjjDlnC3ABg4uQKB2mHrE.jpeg">
Then it goes to my controller:
public function update(Request $request, $id)
{
$company = Company::find($id);
$company->name = $request->input('name');
$company->address = $request->input('address');
// $company->logo = $request->input('logo');
if(null !== (($request->file('logo')))) {
File::delete('logo/' . $request->input('old_logo'));
$request->file('logo')->store('logo');
$company->logo = $request->file('logo')->hashName();
}
$company->save();
return redirect('admin/companies');
}
My file that I want to delete is stored in storage/app/public/logo/
Filesystems.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app/public'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
],
],
];
It should be trying to delete from storage/app/public/logo/ ? As I tested $request->input('old_logo') is passed successfully as well. What I'm doing wrong? Can it be rights problem?
Ofcourse I wrote this: use File;
You need to pass the full path to the file. So, if the file is in public/logo directory, do this:
File::delete(public_path('logo/' . $request->old_logo));
Currently I upload files to my bucket with this code:
function upload_file_to_gcs($source, $des) {
global $gcs;
$bucketName = 'example';
$file = fopen($source, 'r');
$bucket = $gcs->bucket($bucketName);
try {
$result = $bucket->upload($file, [
'name' => $des,
'Content-Type' => 'application/zip'
]);
}
}
But now I want to set the Storage Class, this file should be uploaded to. How can I do that?
In the Amazon AWS I was able to simply set the storage class like:
$result = $s3->putObject([
'Bucket' => 'example',
'Key' => 'folder/'.$des,
'StorageClass' => 'STANDARD_IA', // <--- Simple options command
'ServerSideEncryption' => 'AES256',
'SourceFile' => $source,
'Content-Type' => 'application/zip'
]);
But how can I do this with the Google Storage? I couldn't find any option within the documentation:
http://googlecloudplatform.github.io/google-cloud-php/#/docs/google-cloud/v0.31.1/storage/bucket?method=upload
Does this work?
$result = $bucket->upload($file, [
'name' => $des,
'metadata' => [ 'storageClass' => 'regional' ]
]);