How to set User ID to Storage path in Laravel? - php

I'm building an Restful API using Laravel 5 and MongoDB.
I'm saving avatar image for users.
It's working fine but I'm trying to create a Folder for every User. For example: "app/players/images/USERID"
I've tried to do something like this in different ways but I always get Driver [] is not supported.
\Storage::disk('players'.$user->id)->put($image_name, \File::get($image));
UploadImage:
public function uploadImage(Request $request)
{
$token = $request->header('Authorization');
$jwtAuth = new \JwtAuth();
$user = $jwtAuth->checkToken($token, true);
$image = $request->file('file0');
$validate = \Validator::make($request->all(), [
'file0' => 'required|image|mimes:jpg,jpeg,png'
]);
if ( !$image || $validate->fails() )
{
$data = array(
'code' => 400,
'status' => 'error',
'message' => 'Image uploading error-'
);
}
else
{
$image_name = time().$image->getClientOriginalName();
\Storage::disk('players')->put($image_name, \File::get($image));
$user_update = User::where('_id', $user->id)->update(['imagen' => $image_name]);
$data = array(
'code' => 200,
'status' => 'success',
'user' => $user->id,
'imagen' => $image_name
);
}
return response()->json($data, $data['code']);
}
filesystems.php:
'players' => [
'driver' => 'local',
'root' => storage_path('app/players/images/'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
I expect the user avatar image saves on User ID folder.

The disk call, tells Laravel which filesystem to use, let's assume you have an user with Id one, with your code it will access the filesystem playeers1.
What usually is done is to put these files in folder structures for the different users, so instead you could do. This will put your image file, in the folder 1.
\Storage::disk('players')->put($user->id . '/' . $image_name, \File::get($image));

I had a similar problem, check if the lines can change what you want to achieve.
\Storage::disk('players')->put("{$user->id}/{$image_name}", \File::get($image));
I relied on the laravel guide: File Storage - File Uploads
I hope it helps you. A cordial greeting.

Related

How to send Image or file to the external API using HTTP Client?

I have an API to save images and files
this is the code to save the image request from the API
$file = $request->file('gambar');
$fileName = $file->getClientOriginalName();
$file->storeAs('images/berita', $fileName);
$berita = new Berita;
$berita->judul = $request->judul;
$berita->kategori_id = $request->kategori_id;
$berita->isi = $request->isi;
$berita->gambar = $fileName;
$berita->tgl = $request->tgl;
$berita->user_id = $request->user_id;
$berita->save();
return response()->json([
'message' => 'Data berita Added Successfully!',
'Added berita' => $berita
], Response::HTTP_OK);
I already try the API in postman, and everything went well, image sucessfully uploaded.
Then on the client side, I'm using HTTP Client from Laravel to POST the data to the API. And here's the code.
$Berita = Http::withToken('xxx')
->attach('attachment', file_get_contents($request->file('gambar')))
->post('https://api.xxx.my.id/xxx', [
'judul' => $request->judul,
'kategori_id' => $request->kategori_id,
'isi' => $request->isi,
'gambar' => file_get_contents($request->file('gambar')),
'tgl' => $request->tgl,
'user_id' => $request->user_id
]);
return $Berita;
All the data send successfully, except the gambar which contains the image that i sent. It says that in my API validation.
The gambar must be a file of type: jpeg, jpg, png.
It thought that means the image that i send is sent as a string, so it didn't receive it as a file.
By the way, here's the Laravel documentation about HTTP Client: https://laravel.com/docs/9.x/http-client#multi-part-requests
Does anyone knows how to correctly using it? I think i've misused it.
I think there is problem with attachment.
return Http::withToken('xxx')
->attach('gambar', file_get_contents($request->file('gambar')), , 'gambar.png')
->post('https://api.xxx.my.id/xxx', [
'judul' => $request->judul,
'kategori_id' => $request->kategori_id,
'isi' => $request->isi,
'tgl' => $request->tgl,
'user_id' => $request->user_id
]);
or
return Http::withToken('xxx')
->attach('gambar', $request->file('gambar'), 'gambar.png')
->post('https://api.xxx.my.id/xxx', [
'judul' => $request->judul,
'kategori_id' => $request->kategori_id,
'isi' => $request->isi,
'tgl' => $request->tgl,
'user_id' => $request->user_id
]);
This is because the server cannot read your data.
You should send the data using the application/x-www-form-urlencoded content type, you can achieve this as Laravel documentation says:
$response = Http::asForm()->post('http://example.com/users', [
'name' => 'Sara',
'role' => 'Privacy Consultant',
]);

Disk [public] does not have a configured driver. in laravel image upload

I am trying to upload a file to a public folder which was working lately but now it is showing below error:
Disk [public] does not have a configured driver.
I tried checking for configured driver in config/filesystems.php but, it is already set there. I am not getting where the issue might be.
Upload code:
public function upload(ProductImageRequest $request, Product $product)
{
$image = $request->file('file');
$dbPath = $image->storePublicly('uploads/catalog/'.$product->id, 'public');
if ($product->images === null || $product->images->count() === 0) {
$imageModel = $product->images()->create(
['path' => $dbPath,
'is_main_image' => 1, ]
);
} else {
$imageModel = $product->images()->create(['path' => $dbPath]);
}
return response()->json(['image' => $imageModel]);
}
Code in 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',
],
i use this code for moving the picture and storing its name you may want to give it a shot
//get icon path and moving it
$iconName = time().'.'.request()->icon->getClientOriginalExtension();
$icon_path = '/category/icon/'.$iconName;
request()->icon->move(public_path('/category/icon/'), $iconName);
$category->icon = $icon_path;
i usually move the image then store its path in db and this is what my code shows you can edit it as desired

net::ERR uploading files with Laravel 5.6

I'm getting this error POST http://localhost:8000/dashboard/laws/create net::ERR_FAILED when I try to store a file into my laravel app using an axios request. I'm not sure why this is happening, so if anyone can help me please... :(
if ($request->validate(
[
'name' => 'required|string',
'description' => 'required|string',
'type' => 'required|in:nati,inter',
'file' => 'required|mimetypes:application/pdf'
]
)) {
// Save the file
$file = new LegalFile($request->except(['file']));
// save file in the storage
$file->setFilePath();
$file->file_order = LegalFile::where('type', $file->type)->count();
$file->save();
$disk= Storage::disk('s3');
$disk->put('files', file_get_contents($request->file('file')));
return response('Archivo guardado exitosamente', 200);
}

How to test upload file in laravel 5.0?

I want to test my file upload action .
I checked file type validation on that action . It is working from browser interaction , but I tried with phpunit it fail on validation .
I validate for accepting jpg or jpeg file only .
Here is my unit code
public function testWIthJpgImage()
{
$_FILES = [
'front_image' => [
'name' => 'uitest',
'type' => 'image/jpeg',
'size'=> filesize(storage_path('data/uitest.jpg')),
'error' => 0,
'tmp_name' => storage_path('data/uitest.jpg')
]
];
$response = $this->call('POST', '/api/test',[],[],$_FILES);
$data = json_decode($response->getContent());
dd($data); // here validation fail always
$this->assertEquals(200, $response->getStatusCode());
}
How can I test with file upload correctly on phpunit ? My laravel version 5.0 (old version) Laravel UploadFile is not available
You can use Illuminate\Http\UploadedFile Facade for this.
Here is an example of one of my projects where I upload & store a file. It also has a files table & model.
/** #test */
function create_new_file ()
{
$payload = [
'file' => UploadedFile::fake()->image('avatar.jpg')
];
// act
$response = $this->post("/api/files", $payload);
// test
$response->assertStatus(201);
Storage::disk('local')->assertExists(File::first()->path);
}
Don't forget
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
In addition you can use
Storage::fake('local');
in order to not persist the uploaded files (if you are using the Storage as I do). This is very handy so your tests don't create a bunch of files in your uploads folder.
I think my problem is sovled but it is so weired to do that :) I set $_FILES and Symfony UploadedFile both :<
$_FILES = [
'front_image' => [
'name' => 'uitest',
'type' => 'image/jpeg',
'size'=> filesize(storage_path('data/uitest.jpg')),
'error' => 0,
'tmp_name' => storage_path('data/uitest.jpg'),
'test' => true
]
];
$uploadedFile = new Symfony\Component\HttpFoundation\File\UploadedFile(
storage_path('data/uitest.jpg'),
'uitest.jpg',
'image/jpeg',
filesize(storage_path('data/uitest.jpg')),
0,
true
);
$response = $this->call('POST', '/api/test',[],[],['front_image' => $uploadedFile]);

Test an upload with PHPUnit in Laravel

Currently, i try to test a file upload with PHPUnit for Laravel. After some searches, i found a first solution :
$file = new \Symfony\Component\HttpFoundation\File\UploadedFile(
app_path() . '/tests/Files/default.png', 'default.png');
$response = $this->call('POST', 'students',
[
'firstname' => 'firstname',
'lastname' => 'lastname',
'promotion' => '2016',
'isCoop' => 1
],
[
'avatar' => [$file]
]
);
It works, but it failed when I push this code on Travis, and i'm not sure it's very clean to do that...
You can see my test failed here.
Thank's you.
You should use virtual file system for your tests. Check mocking file system in the phpunit documentation
You can use this class \Illuminate\Http\UploadedFile to test your upload file as you can see on this answer
mine working using test case like this :
public function testUploadLanscapseValid()
{
$uploadFile= new \Illuminate\Http\UploadedFile(
base_path()."/resources/fakerFile/mobileScreen/bg_land.jpg", //path image
'example.jpg',
'image/jpeg',
filesize(base_path()."/resources/fakerFile/mobileScreen/bg_land.jpg"), // file size
null,
true
);
//checking UI validation response
$this->visit('/mobile-screen')
->attach($uploadFile, 'image-landscape')
->press('upload-image-landscapse')
->seePageIs('/mobile-screen')
->see('Mobile screen successfully uploaded.');
//checking database is inserted
$this->seeInDatabase('mobile_screen',['link_lanscapse'=>'bg_land.jpg']);
//checking file exist
if(file_exists(base_path() . '/public/mobileScreen/bg_land.jpg')){
$this->assertTrue(true);
}else{
$this->assertTrue(false);
}
}
when you are testing upload using file please use \Illuminate\Http\UploadedFile instead of \Symfony\Component\HttpFoundation\File\UploadedFile
UPDATE
when seeing your test I think it is incomplete you can get the response of your test like mine here :
public function testUploadFunctionalTest()
{
$uploadedFile= new \Illuminate\Http\UploadedFile(
base_path()."/resources/fakerFile/mobileScreen/bg_land.jpg", //path image
'example.jpg',
'image/jpeg',
filesize(base_path()."/resources/fakerFile/mobileScreen/bg_land.jpg"), // file size
null,
true
);
// you can use this or
$parameters = [];
$response = $this->action(
'POST',
'AdminWeb\MobileScreenController#store',
[],
$parameters,
[],
['image' => $uploadedFile]
);
// you can use this choose One !
$response =$this->call('POST', 'mobile-screen#store',
[
'firstname' => 'firstname',
'lastname' => 'lastname',
'promotion' => '2016',
'isCoop' => 1
],
[
'image' => [$uploadedFile]
]);
$result = json_decode($response->content()); // you can dump or whatever you want with the test
var_dump($result->your_response);
$this->assertEquals($result->your_response,'expected output');
}
Note : I'm using laravel 5.2, and this test will write the file on your disk
$file = new \Symfony\Component\HttpFoundation\File\UploadedFile(
app_path() . '/tests/Files/default.png', 'default.png', "image/jpeg", null, null, true);

Categories