Laravel not storing files from request - php

I got form with file upload named "image". Form is working and i'm getting image but for some reason it's not stored. this is the code I use to store image:
$path = $request->image->store('storage/uploads');
before that I check
$request->hasFile('image')
and later I'm saving $path. Path is successfully saved and when i check it it's really storage/uploads/radnomid but there is no file

If your filesystems.php configs were default then
$path = $request->image->store('storage/uploads');
saved your files not in storage/uploads but in storage/app/storage/uploads.
And your current accepted answer is not really good because public_path() intended to be used for storing template files not user uploads. According to official docs uploads should be used in storage/ folder with a symbolic link from public/storage/ but not in public/.
Read more in https://laravel.com/docs/5.4/filesystem#the-public-disk

Sorry for posting my own answer but problem was that by default laravel public disk does not upload to public directory. Settings needed to be changed like this:
config/filesystems.php
'public' => [
'driver' => 'local',
'root' => public_path(),
'visibility' => 'public',
],
and then simply:
$path = $request->image->store('storage/uploads','public');

you can try with this code,
Image::make($request->file('image'))->save('upload_path/filename.jpg'));
here is complete doc of this Image package.
http://image.intervention.io/

Make sure that you are including enctype of multipart/form-data. You can either add the attribute directly to your form, or you can add a 'files' => true if you are using the FORM helper.
This is the conventional way to use the upload function that comes with Laravel 5.
public function processForm(Request $request)
{
if( $request->hasFile('image') ) {
$file = $request->file('image');
// Now you have your file in a variable that you can do things with
}
}

Try doing like this
if ($request->hasFile('image')) {
$image = $request->file('image');
$filename = time() . '.' . $image->getClientOriginalExtension();
$location = public_path('images/comment/' . $filename);
Image::make($image)->resize(800, 600)->save($location);
}

I think you should try this:
Image::make($request->file('image'))->save(storage_path('uploads/image.jpg'));
Hope this works for you!

Related

Why is Laravel renaming the file extension of the image that I upload? [duplicate]

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;

How to save images in public_html instead of the default storage in laravel?

Laravel shared hosting saving images problem:
Situation:
Can't create symlink() "symlink() has been disabled for security
reasons"
no ssh support just ftp
How to save images to public_html lets say to a file storage/cover_image
This was the shortcut generated during development
if($request->hasFile('cover_image')){
// Get filename with the extension
$filenameWithExt = $request->file('cover_image')->getClientOriginalName();
// Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
// Get just ext
$extension = $request->file('cover_image')->getClientOriginalExtension();
// Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
// Upload Image
Storage::disk('my_upload')->put($fileNameToStore, $request->file('cover_image'));
//$path = $request->file('cover_image')->storeAs('public/cover_images', $fileNameToStore);
} else {
$fileNameToStore = 'noimage.jpg';
}
I made a custom disk in called my_upload i cant figure out where it saves the file but it doesn't save in public_html/storage/cover_images
//custom my_disk code
'my_upload' => [
'driver' => 'local',
'root' => public_path().'/storage/cover_images',
'visibility' => 'public',
],
if i use storeAs it always stores storage that is not in public_html its also not an issue with permissions since am still testing i have set the permissions to 777
Looks like you are on shared hosting, what I know most hosting providers has their rules to php.ini configurations cmiiw.
So, if you want put your image on public_html, you can do like this:
$path = '/home/{your_shared_hosting_username}/public_html/cover_image';
$request->file('cover_image')->move($path, $filename);
After hours of research and grinding solved my problem eventually... to help other me's.
Step 1:
Create a custom disk in config/filesystem.php
//In my case
'my_upload' => [
'driver' => 'local',
'root' => public_path().'/storage',
'visibility' => 'public',
],
Step 2:
Change public_path() to public_html
//What worked for me
//Changed file: public_html/index.php
//after bootstrap declaration-> this is important
$app->bind('path.public', function() {
return __DIR__;
});
Step 3:
Now save your file like this
// Handle File Upload
if($request->hasFile('cover_image')){
// Get filename with the extension
$filenameWithExt = $request->file('cover_image')->getClientOriginalName();
// Get just filename
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
// Get just ext
$extension = $request->file('cover_image')->getClientOriginalExtension();
// Filename to store
$fileNameToStore= $filename.'_'.time().'.'.$extension;
// Upload Image
$path = $request->file('cover_image')->storeAs('cover_images', $fileNameToStore,['disk' => 'my_upload']);
if(!$path){
return false;
}
} else {
$fileNameToStore = 'noimage.jpg';
}
In my case my images will be saved in public_html/storage/cover_images
Resources:
How to upload files in Laravel directly into public folder?
However that doesn't cut it since images are stored in the laravel public so you have to change the default laravel public to your now public_html which is your public in shared hosting.
https://laracasts.com/discuss/channels/general-discussion/where-do-you-set-public-directory-laravel-5
Tested on laravel 5.8
NB: I also noted running laravel config:cache breaks the saving location..you should probably avoid this command.
Incase you already ran the command config:clear undo's

Laravel - Display preview of file stored in Storage directory

I have to upload some files for each users, and the files should not be accessible publicly.
When a user a created, I'm creating a folder in storage directory using-
Storage::makeDirectory($user->ref_id);
Now I've a files table, which stores the file details. Here is the code for uploading file and saving the path to the database.
$this->validate($request, [
'file' => 'required|mimetypes:image/png,image/jpeg,application/pdf',
]);
$user = Auth::user();
$filename = time() . '.' . $request->file->getClientOriginalExtension();
$path = $request->file('file')->storeAs($user->ref_id, $filename);
$user->files()->create(['file_name' => $path]);
The file is being stored successfully. Now when a user logs in, I want to display a preview of that file in the view.
Any help, how can I do that??
This is how you serve a file from a controller. Instead of returning a view you return the file like this. In case of an image you can't echo it directly to the view unless you base64 encode it (which increases the filesize).
return response()
->download($file_path, "file_name",
[
'Content-Type' => 'application/octet-stream'
]);
Make a function in your controller containing the code above and some logic to retrieve the right file path and make a route for it.
After you've done that you can (for example) add in your view
<img src="{{route('ROUTE_NAME')}}">
You'll have to fill in all the variables yourself ofcourse.
Using this method the files will always stay private and will only be echoed once you allowed the user access. Note that this WILL use more recourses as you let PHP handle serving the file instead of apache. Hope this helps!
This solved my problem...
https://stackoverflow.com/a/41322072/6792282
I used this in my code and preview is working fine for pdf files..
<embed name="plugin" src="{{url('/')}}/{{ Storage::disk('local')->url($file->file_name)}}" type="application/pdf">

File not found at path when trying to copy

I'm trying to copy a file from one location to another. I'm pretty sure the location is correct, but I'm still getting the error in the title.
Here's some code:
$oDirectory = new \RecursiveDirectoryIterator($extractFolder.'/res');
$oIterator = new \RecursiveIteratorIterator($oDirectory);
foreach($oIterator as $oFile) {
if ($oFile->getFilename() == 'icon.png') {
$icons[filesize($oFile->getPath().'/icon.png')] = $oFile->getPath().'/icon.png';
}
}
asort($icons);
print_r($icons);
$icon_source = end($icons);
echo $icon_source;
$generated_icon_file = str_slug($packagename.$version).'.png';
Storage::copy($icon_source, $generated_icon_file);
The print_r returns (which means the files exist):
Array ( [19950] => /var/www/apk.land/storage/extracted_apks/res/drawable-xxhdpi-v4/icon.png [31791] => /var/www/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png [6979] => /var/www/apk.land/storage/extracted_apks/res/drawable-hdpi-v4/icon.png [10954] => /var/www/apk.land/storage/extracted_apks/res/drawable-xhdpi-v4/icon.png )
The echo returns:
/var/www/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png
And the exact error is:
File not found at path:
var/www/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png
P.S. PHP's copy function works just great.
I can't find the problem here.
Any suggestions?
You said that the error is like this:
File not found at path: var/www/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png
Here error is saying it cannot find at var/www that means it's looking for apk.land/var/www whereas your file is located somewhere at /var/www. A quick fix to this can be use file protocol. Just use it like:
file:///var/www/storage/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png
Try with File::copy($file, $dest) instead of Storage::copy($old, $new)
File::copy() is the wrapper on PHP's copy() function
First of all, if you are using Laravel's Storage Facade and with that the underlying Flysystem you have to know, that it is not intended to work with absolute paths like you did. The benefit of that is, that you could potentially work with different storage disks, that all have own configurations, that can be set in your config/filesystems.php file.
Assuming you did not change anythig there, the default "disk" would be local with an root of storage_path('app') ( = the path to your laravel storage folder/app )
If you want to know, why it is failing, we have to take a look at the source code you will find in the following code in the file vendor\league\flysystem\src\Filesystem.php
public function copy($path, $newpath)
{
$path = Util::normalizePath($path); // <-- this will strip leading /
$newpath = Util::normalizePath($newpath);
$this->assertPresent($path); // this will cause the error in your case, because assertion cannot be fullfilled in case of missing leading /
$this->assertAbsent($newpath);
return $this->getAdapter()->copy($path, $newpath); // calls the copy of your Adapter, assuming local in your case
}
So have a look, what would go on, if $this->getAdapter()->copy($path, $newpath) was called:
File (assuming local storage disk): vendor\league\flysystem\src\Adapter\Local.php
public function copy($path, $newpath)
{
$location = $this->applyPathPrefix($path);
$destination = $this->applyPathPrefix($newpath);
$this->ensureDirectory(dirname($destination));
return copy($location, $destination);
}
The line
$location = $this->applyPathPrefix($path);
will prepend the root path as defined in config/filesystems.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
As I can see in your code your files are are not stored in storage/app,
so i think you have to change this to 'root' => storage_path()
So if you want to use Storage::copy() you have just to provide paths relative to that folder. And as it is hard to see, how you could achieve this, take a look at that.
foreach($oIterator as $oFile) {
if ($oFile->getFilename() == 'icon.png') {
$icons[filesize($oFile->getPath().'/icon.png')] = $oIterator->getSubPath().'/icon.png';
}
}
There is RecursiveDirectoryIterator::getSubPath (Although quite undocumentated, which would return you the current subpath of your iterations. In your case relative to $extractFolder.'/res'.
Now you have to make sure you are calling
Storage::copy($icon_source, $generated_icon_file);
Where $icon_source and $generated_icon_file are relative to your defined 'root'.
Insert / before var/www/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png
The path is relative to current directory. Buy if you add /, the path is absolute from root directory.
you have to choose the right disk somthing like this
$file2 ='public/'.$page->thumbnail;
$destination = 'public/bundles/ttt.png';
if( Storage::disk('local')->exists($file2)){
Storage::disk('local')->copy($file2,$destination);
}

Cannot save image intervention image. NotWritableException in Image.php line 138

Im trying to save a manipulated image which i will them push to s3.
My code that works This code saves the image directly within the public folder*
public function store(Filesystem $filesystem)
{
$request = Input::all();
$validator = Validator::make($request, [
'images' => 'image'
]);
if ($validator->fails()) {
return response()->json(['upload' => 'false']);
}
$postId = $request['id'];
$files = $request['file'];
$media = [];
$watermark = Image::make(public_path('img/watermark.png'));
foreach($files as $file) {
$image = Image::make($file->getRealPath());
$image->crop(730, 547);
$image->insert($watermark, 'center');
$image->save($file->getClientOriginalName());
}
}
What i would like to achieve is to be able to save it within a folder of it's own. Firstly what is the best place to store an image for a blog post, within the storage of public folder? But anyway when i do this:
$image->save('blogpost/' . $postId . '/' . $file->getClientOriginalName());
// Or this
$image->save(storage_path('app/blogpost/' . $postId . '/' . $file->getClientOriginalName()));
I get the error:
folder within public
NotWritableException in Image.php line 138: Can't write image data to
path (blogpost/146/cars/image.jpg)
or
storage path
NotWritableException in Image.php line 138: Can't write image data to
path /code/websites/blog/storage/app/blogpost/146/image.jpg
I've tried
cd storage/app/
chmod -R 755 blogpost
And it still wont work
Thank you for reading this
Ok so here is how i solved it, I made the directory first before storing,
Storage::disk('local')->makeDirectory('blogpost/' . $postId);
Once the folder is created i then go on to store the manipulated images like so:
$image->save(storage_path('app/blogpost/' . $postId . '/' . $imageName));
And then pushing the image to S3
$filesystem->put('blogpost/' . $postId . '/' . $imageName, file_get_contents(storage_path('app/blogpost/' . $postId . '/' . $imageName)));
This worked
You can solve it by casting the Intervation/Image variable to a data stream using function stream. Then use the Storage Laravel facade to save the image.
$img = Image::make('path-to-the-image.png')->crop(...)->insert->stream('jpg', 90)
Storage::put('where_I_want_the_image_to_be_stored.jpg', $img);
Laravel 5 needs permission to write to entire Storage folder so try following,
sudo chmod 755 -R storage
if 755 dont work try 777.
Am improving #Amol Bansode answer.
You are getting this error because $postId folder does not exist in the path you specified.
You could do it like this:
//I suggest you store blog images in public folder
//I assume you have created this folder `public\blogpost`
$path = public_path("blogpost/{$postId}");
//Lets create path for post_id if it doesn't exist yet e.g `public\blogpost\23`
if(!File::exists($path)) File::makeDirectory($path, 775);
//Lets save the image
$image->save($path . '/' . $file->getClientOriginalName());
In my case I migrated a project from Windows 10 to Parrot (Debian-Linux) and I had the same problem and turned out the slashes were backward slashes and Linux interpret them differently. Unlike Windows, it doesn't really matter.
//Windows Code:
$image_resize->save(public_path('\storage\Features/' .'Name'.".".'png'));
//Linux Code (Working):
$image_resize->save(public_path('storage/Features/' .'Name'.".".'jpg'));
I know the question is related to Laravel but I came across from making it to work with WordPress. If somebody is coming from WordPress world, this code works (I was getting the same 'cannot write' error) and changing directory permission would not work as the library probably needs the relative path (the code below is valid for direct installation of Intervention through composer into any PHP application, not Laravel per se)-
require 'vendor/autoload.php';
use Intervention\Image\ImageManager;
$manager = new ImageManager(array('driver' => 'imagick'));
$image = $manager->make('PUBLIC IMAGE URL/LOCAL IMAGE PATH');
$image->crop(20, 20, 40, 40);
$image->save(__DIR__ . '/img/bar.png');
in my case:
i double check my symlinks in filesystem.php in config folder in laravel
and remove all symlink then regenerate them
php artisan storage:link
in my case my fileName is not valid format for naming in windows but it worked on linux or docker
$make_name = date('Y-m-d-H:i:s') . hexdec(uniqid()) . '.' . $img->getClientOriginalExtension();
when I remove this date('Y-m-d-H:i:s') it worked as well
I have faced the same issue but 775 permission not sort it so I changed the write permission to the folder(also sub-folders) to 777 to get over this issue.

Categories