Laravel default Storage path change - laravel

I want to save image in main public folder using laravel file storeAs method. Is there anyway to change the path in using this code?
$path = $request->img->storeAs('images', 'filename.jpg');
I'm already try add new disks in filesystems.php to this
'my' => [
'driver' => 'local',
'root' => public_path('app'),
'visibility' => 'public',
],
and store using this code
Storage::disk('my')->put('filename.jpg', $request->img);
but using above code it make new folder name 'filename.jpg' and save image inside that folder using random name. But I want to save that image name that 'filename.jpg'.
thank you.

You can do this very easily
$imageName = $request->file('image_name')->getClientOriginalName();
$directory = 'your/directory/path/';
$imageUrl = $directory . $imageName;
$productImage->move($directory, $imageName);

It is not in the documentation but if you check storeAs method implementation (https://github.com/laravel/framework/blob/7.x/src/Illuminate/Http/UploadedFile.php#L80) you'll see that it is possible to pass an array of options as the third parameter. The disk key is used to set witch should be used. So your code would be:
$path = $request->img->storeAs('images', 'filename.jpg', ['disk' => 'my');
Bear in mind that if you are storing in a path that does not exists it is necessary to give the parent folder permission to create new directories.

Related

Image storing on S3 publicly returns false

The following code returns a path and an image gets uploaded to S3 (as a working code reference):
dd(Storage::disk('s3')->put('images/', $file));
Once I add either 'visibility' => 'public' to the s3 driver in config/filesystems.php or 'public' as 3rd argument ($options) of put, it returns false.
In the s3 bucket configuration I disabled blocking of public access.
The following code returns false as well:
$path = Storage::disk('s3')->put('images/', $file);
dd(Storage::disk('s3')->setVisibility($path, 'public'));
Following the Laravel documentation, they recommend the usage of
Storage::putFile('photos', new File('/path/to/photo'), 'public');
but the putFile function is not available when I use
Storage::disk('s3')->putFile('photos', new File('/path/to/photo'), 'public');
Try with putFileAs, Ex:
$path: s3 Path
$image: Uploaded Image
$fileName: Filename
Storage::disk('s3')->putFileAs($path, $image, $fileName, 'public');

Laravel Intervention - Unable to init from given binary data

I am using "intervention/image": "^2.5" in one of my projects. It is working well except for one part of the code where im retrieving an image.
I keep getting a Unable to init from given binary data error and i cant figure out why.
The file exists but i cant figure it out.
My code is as follows;
$path = '/image-storage/492/1/testimage.jpg';
$file = Storage::get($path);
ob_end_clean();
return Image::make($file)->response();
Below is my filesystem.php config for local
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
Storage::get($path) returns file contents as a string which may not be cast to valid binary data for Image::make() to be able to read.
You can try by passing the path to the image to the make method
//If testimage.jpg is located at storage/app/image-storage/492/1
$path = storage_path('app/image-storage/492/1/testimage.jpg');
//if testimage.jpg is located at storage/app/public/image-storage/492/1/, then
//$path = storage_path('app/public/image-storage/492/1/testimage.jpg');
return Image::make($path)->response();
OR you can create a new Illuminate\Http\File instance and then pass it to the make method
//If testimage.jpg is located at storage/app/image-storage/492/1
$path = storage_path('app/image-storage/492/1/testimage.jpg');
//if testimage.jpg is located at storage/app/public/image-storage/492/1/, then
//$path = storage_path('app/public/image-storage/492/1/testimage.jpg');
$file = new \Illuminate\Http\File($path);
Image::make($file)->response();
Intervention image accepts binary data or SplFileInfo instance. Illuminate\Http\File extends Symfony\Component\HttpFoundation\File\File which extends \SplFileInfo.
Intervention Image - Reading Images

Laravel, getting uploaded file's url

I'm currently working on a Laravel 5.5 project, where I want to upload files, and then, I want to get their url back of the file (I have to use it client side).
now my code looks like this:
public function pdfUploader(Request $request)
{
Log::debug('pdfUploader is called. ' . $request);
if ($request->hasFile('file') && $request->file('file')->isValid()) {
$extension = $request->file->extension();
$fileName = 'tmp' . round(microtime(true) * 1000) . '.' . $extension;
$path = $request->file->storeAs('temp', $fileName);
return ['status' => 'OK', 'path' => URL::asset($path)];
}
return ['status' => 'NOT_SAVED'];
}
It works fine, I got back the OK status, and the path, but when I want to use the path, I got HTTP 404. I checked, the file is uploaded fine..
My thought is, I should register the new url in the routes. If I have to, how can I do it dynamically, and if its not necessary what is wrong with my function?
Thx the answers in advance.
By default laravel store all uploaded files into storage directory, for example if you call $request->file->storeAs('temp', 'file.txt'); laravel will create temp folder in storage/app/ and put your file there:
$request->file->storeAs('temp', 'file.txt'); => storage/app/temp/file.txt
$request->file->storeAs('public', 'file.txt'); => storage/app/public/file.txt
However, if you want to make your uploaded files accessible from the web, there are 2 ways to do that:
Move your uploaded file into the public directory
$request->file->move(public_path('temp'), $fileName); // => public/temp/file.txt
URL::asset('temp/'.$fileName); // http://example.com/temp/file.txt
NOTE: make sure that your web server has permissions to write to the public directory
Create a symbolic link from storage directory to public directory
php artisan storage:link
This command will create a symbolic link from public/storage to storage/app/public, in this case we can store our files into storage/app/public and make them accessible from the web via symlinks:
$request->file->storeAs('public', $fileName); // => storage/app/public/file.txt
URL::asset('storage/'.$fileName); // => http://example.com/stoage/file.txt

Laravel : To rename an uploaded file automatically

I am allowing users to upload any kind of file on my page, but there might be a clash in names of files. So, I want to rename the file automatically, so that anytime any file gets uploaded, in the database and in the folder after upload, the name of the file gets changed also when other user downloads the same file, renamed file will get downloaded.
I tried:
if (Input::hasFile('file')){
echo "Uploaded</br>";
$file = Input::file('file');
$file ->move('uploads');
$fileName = Input::get('rename_to');
}
But, the name gets changed to something like:
php5DEB.php
phpCFEC.php
What can I do to maintain the file in the same type and format and just change its name?
I also want to know how can I show the recently uploaded file on the page and make other users download it??
For unique file Name saving
In 5.3 (best for me because use md5_file hashname in Illuminate\Http\UploadedFile):
public function saveFile(Request $request) {
$file = $request->file('your_input_name')->store('your_path','your_disk');
}
In 5.4 (use not unique Str::random(40) hashname in Illuminate\Http\UploadedFile). I Use this code to ensure unique name:
public function saveFile(Request $request) {
$md5Name = md5_file($request->file('your_input_name')->getRealPath());
$guessExtension = $request->file('your_input_name')->guessExtension();
$file = $request->file('your_input_name')->storeAs('your_path', $md5Name.'.'.$guessExtension ,'your_disk');
}
Use this one
$file->move($destinationPath, $fileName);
You can use php core function rename(oldname,newName) http://php.net/manual/en/function.rename.php
Find this tutorial helpful.
file uploads 101
Everything you need to know about file upload is there.
-- Edit --
I modified my answer as below after valuable input from #cpburnz and #Moinuddin Quadri. Thanks guys.
First your storage driver should look like this in /your-app/config/filesystems.php
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'), // hence /your-app/storage/app/public
'visibility' => 'public',
],
You can use other file drivers like s3 but for my example I'm working on local driver.
In your Controller you do the following.
$file = request()->file('file'); // Get the file from request
$yourModel->create([
'file' => $file->store('my_files', 'public'),
]);
Your file get uploaded to /your-app/storage/app/public/my_files/ and you can access the uploaded file like
asset('storage/'.$yourModel->image)
Make sure you do
php artisan storage:link
to generate a simlink in your /your-app/public/ that points to /your-app/storage/app/public so you could access your files publicly. More info on filesystem - the public disk.
By this approach you could persists the same file name as that is uploaded. And the great thing is Laravel generates an unique name for the file so there could be no duplicates.
To answer the second part of your question that is to show recently uploaded files, as you persist a reference for the file in the database, you could access them by your database record and make it ->orderBy('id', 'DESC');. You could use whatever your logic is and order by descending order.
You can rename your uploaded file as you want . you can use either move or storeAs method with appropiate param.
$destinationPath = 'uploads';
$file = $request->file('product_image');
foreach($file as $singleFile){
$original_name = strtolower(trim($singleFile->getClientOriginalName()));
$file_name = time().rand(100,999).$original_name;
// use one of following
// $singleFile->move($destinationPath,$file_name); public folder
// $singleFile->storeAs('product',$file_name); storage folder
$fileArray[] = $file_name;
}
print_r($fileArray);
correct usage.
$fileName = Input::get('rename_to');
Input::file('photo')->move($destinationPath, $fileName);
at the top after namespace
use Storage;
Just do something like this ....
// read files
$excel = $request->file('file');
// rename file
$excelName = time().$excel->getClientOriginalName();
// rename to anything
$excelName = substr($excelName, strpos($excelName, '.c'));
$excelName = 'Catss_NSE_'.date("M_D_Y_h:i_a_").$excelName;
$excel->move(public_path('equities'),$excelName);
This guy collect the extension only:
$excelName = substr($excelName, strpos($excelName, '.c'));
This guy rename its:
$excelName = 'Catss_NSE_'.date("M_D_Y_h:i_a_").$excelName;

Access $_FILE['tmp_name'] from the UploadedFile class?

if I print the content of an instance of UploadedFile, this is what I get
array (
'opt_image_header' =>
Symfony\Component\HttpFoundation\File\UploadedFile::__set_state(array(
'test' => false,
'originalName' => 'triangle-in-the-mountains.jpg',
'mimeType' => 'image/jpeg',
'size' => 463833,
'error' => 0,
)
And this is how I get the uploaded file in the Controller. Before of moving it, I should resize it.
foreach($request->files as $uploadedFile){
$ext = '.' . $uploadedFile['opt_image_header']->guessExtension();
$filename = sha1(uniqid(mt_rand(), true)) . $ext;
$uploadedFile['opt_image_header']->move($path . '/images/', $filename);
}
so there's no the "tmp_name" that I'd need for resizing the image before of saving it.
Do I need to read it directly from the $_FILE array?
Use $uploadedFile->getRealPath()
Symfony\Component\HttpFoundation\File\UploadedFile extends Symfony\Component\HttpFoundation\File\File, which extends PHP's SplFileInfo, so UploadedFile inherits all methods from SplFileInfo.
Use $uploadedFile->getRealPath() for the absolute path for the file. You can also use other methods on it, such as getFilename() or getPathname(). For a complete list of available methods (of SplFileInfo), see the docs.
Symfony's File class adds some extra methods, such as move() and getMimeType(), and adds backward compatibility for getExtension() (which was not available before PHP 5.3.6). UploadedFile adds some extra methods on top of that, such as getClientOriginalName() and getClientSize(), which provide the same information as you would normally get from $_FILES['name'] and $_FILES['size'].
If you are uploading a file with Doctrine, take a look at Symfony Documentation Upload a file
If you want to upload a file without Doctrine, you can try something like:
foreach($request->files as $uploadedFile) {
$filename = $uploadedFile->get('Put_Input_Name_Here')->getClientOriginalName();
$file = $uploadedFile->move($distination_path, $filename);
}
If there was any issue for uploading file move() will throw an exception
UPDATED
According to get the temp path of the uploaded file to resize the image you can use getPath() function in the mentioned loop
$tmp_name = $uploadedFile->get('Put_Input_Name_Here')->getPath();
If you ask why, because the Symfony File class is extends SplFileInfo

Resources