I am trying to get the name of an image and save it instead of saving it as laravel default hashing.
i.e if an image name is go.jpg it should save as go.jpg instead of randomly generated numbers
Here is my controller
private function storeImage($news)
{
if (request()->has('image')){
$news->update([
'image' => request()->image->store('uploads', 'public'),
]);
$image = Image::make(public_path('storage/'. $news->image))->resize(600, 600);
$image->save();
}
}
You can use this method: getClientOriginalName()
if ($request->hasFile('image')) {
return $request->file('image')->getClientOriginalName();
} else {
return 'no file!'
}
http://api.symfony.com/3.0/Symfony/Component/HttpFoundation/File/UploadedFile.html#method_getClientOriginalName
getClientOriginalName use this method.
use Illuminate\Support\Facades\Input;
private function storeImage($news)
{
if (request()->has('image')){
$file = Input::file('image');
$img= $file->getClientOriginalName().'.'.$file->getClientOriginalExtension();
$news->update([
'image' => $img,
]);
$image = Image::make(public_path('storage/'. $news->image))-
>resize(600, 600);
$image->save();
}
}
Related
Task: Upload image on s3 server
The code functioning properly on my local system and the file in saving properly on s3 server but when I push this code on server it gives me the hashName error.
Error: Call to a member function hashName() on null in file /var/www/html/doctring-api/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php on line 240
Code for Image Helper
<?php
namespace App\Helpers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Intervention\Image\Facades\Image;
class UserHelper
{
public static function uploadImage($image)
{
try {
if (count(explode("data:image/", $image)) > 1) {
$fileName = \Carbon\Carbon::now()->timestamp . '_' . uniqid() . '.' . explode('/', explode(':', substr($image, 0, strpos($image, ';')))[1])[1];
$image = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '',$image));
Storage::disk('s3')->put($fileName, $image, 'public');
return $fileName;
}
return true;
} catch (\Exception $e) {
return false;
}
}
}
Api Controller
public function uploadPrescription(Request $request){
$validator = Validator::make($request->all(), [
'patient_id' => 'required',
'appointment_id' => 'required',
'prescription' => 'required'
]);
if($validator->fails()){
return $this->sendError('Validation Error.', $validator->errors());
}
$input = $request->all();
$status_check = Appointment::where('id','=',$input['appointment_id'])->first();
if($status_check->status == 'OnGoing'){
//upload prescription(image in base64) to s3 bucket
if($request->has('prescription'))
{
$imageName = UserHelper::uploadImage($request->prescription);
$input['image_url'] = $imageName;
}
$data=[
'patient_id' => $input['patient_id'],
'appointment_id' => $input['appointment_id'],
'prescription'=> $imageName
];
//Uploading Prescription only one record
// $profile = Prescriptions::updateOrCreate(Arr::except($data, 'prescription'), $data);
$profile = Prescriptions::updateOrCreate($data);
return response()->json(['message' => "Prescription Uploaded", 'profile'=> $profile, 'error'=> 0, 'status'=> 1 ]);
}else{
return response()->json(['message' => "Prescription Uploading Failed", 'error'=> 1, 'status'=> 0 ]);
}
}
At line 240 of Filesystem/FilesystemAdapter as reported by your error, there is this line:
return $this->putFileAs($path, $file, $file->hashName(), $options);
This means that $file is null when you are trying to upload it.
In your question you say that in local environment you don't have this problem, so you should check in the code that precede this, what is causing the problem on the production server environment.
Hope this helps
Trying to implement update article in my update controller it seems works, but the problem is when I only want to update the post without uploading an image the old always getting remove which is it shouldn't.
here's my store function
public function store(Post $post)
{
$post->update($this->validateRequest());
$this->storeImage($post);
return redirect('post/'.$post->id)->with('success', 'New ariticle has been posted');
}
}
here's my validation
private function validateRequest()
{
return request()->validate([
'title'=> 'required',
'content' => 'required',
'image' => 'sometimes|image|max:5000',
]);
}
here's my update function
public function update(Post $post)
{
File::delete(public_path('storage/'.$post->image));
$post->update($this->validateRequest());
$this->storeImage($post);
return redirect('post/'.$post->id)->with('success', 'This post has
been Edited');
}
}
I've tried to add File::delete to my storeImage function and delete it from my update function, it fix the problem but the old image is not removed from directory
private function storeImage($post)
{
if (request()->has('image')){
File::delete(public_path('storage/'.$post->image))
$post->update([
'image' => request()->image->store('uploads', 'public'),
]);
$image = Image::make(public_path('storage/'.$post->image))->fit(750, 300);
$image->save();
}
}
Ok since I use model binding in my controller I don't have to find the id right?
so I change my update function which is basically Akhtar munir suggested, and turn out to be something like this. The image update work, it also remove the old image when I update it. But I have found another issue, the problem is when I edit article and title it didn't change like when I update it, I hope you can take look at this is this correct?
public function update(Post $post){
$this->validateRequest();
if(request()->hasFile('image') && request('image') != ''){
$imagePath = public_path('storage/'.$post->image);
if(File::exists($imagePath)){
unlink($imagePath);
}
$image = request()->file('image')->store('uploads', 'public');
$post->update([
'title' => request()->title,
'content' => request()->content,
'image' => $image,
]);
}
}
This is what I have done in one of my method. It may help you.
public function update(Request $request, $id)
{
if (UserDocument::where('id',$id)->exists()) {
$this->validateUserDocument($request);
if ($request->hasFile('doc_file') && $request->doc_file != '') {
$doc = UserDocument::where('id',$id)->first();
// dd($doc);
$file_path = storage_path().'/app/'.$doc['doc_file'];
//You can also check existance of the file in storage.
if(Storage::exists($file_path)) {
unlink($file_path); //delete from storage
// Storage::delete($file_path); //Or you can do it as well
}
$file = $request->file('doc_file')->store('documents'); //new file path
$doc->update([
'title' => $request->title,
'doc_file' => $file //new file path updated
]);
session()->flash('success','Document updated successfully!');
return redirect()->route('userdocs');
}
session()->flash('error','Empty file can not be updated!');
return redirect()->back();
}
session()->flash('error','Record not found!');
return redirect()->back();
}
In this code, I just simply want to clearify to you that I have stored image path in database, first I have retrieved that path and with that path I have found image in my local storage, delete it first and then update it with the new one. But make sure to store image path in database in both cases ofcourse with insert and update.
So finally you can also optimize your code like this, it will do the same thing as you expect, whether image and all data or only title and content.
public function update(Post $post){
$this->validateRequest();
$data = [
'title' => request()->title,
'content' => request()->content
];
if (request()->hasFile('image') && request('image') != '') {
$imagePath = public_path('storage/'.$post->image);
if(File::exists($imagePath)){
unlink($imagePath);
}
$image = request()->file('image')->store('uploads', 'public');
$data['image'] = $image;
//$post->update($data);
}
$post->update($data);
}
Try this one
private function storeImage($post)
{
if (request()->hasFile('image')){
$image_path = "/storage/".'prev_img_name'; // prev image path
if(File::exists($image_path)) {
File::delete($image_path);
}
$post->update([
'image' => request()->image->store('uploads', 'public'),
]);
$image = Image::make(public_path('storage/'.$post->image))->fit(750, 300);
$image->save();
}
}
I have Image Intervention working and pushing to S3, but I can't save the filename to the table.
this is what I have so far:
// Use AS because Image is already a Nova facade
use Intervention\Image\Facades\Image as Cropper;
- - -
Avatar::make('Image Large')
->store(function (Request $request, $model) {
// Create a UUID filename
$fileName = $this->uuid() . '.jpg';
// Crop with Image Intervention
$cropped = Cropper::make($request->image_large)->fit(100, 50, function ($c) {
$c->upsize();
})->encode('jpg', 80);
// Store on S3
Storage::disk('s3_image')->put($fileName, (string) $cropped);
// Save filename in DB
$model->update([
'image_large' => $fileName,
]);
})
->rules('required')
->prunable(),
All working except the last part, saving the filename.
I figured it out
Avatar::make('Image', 'image_large')
->store(function (Request $request, $model) {
// Create a UUID filename
$fileSmall = $this->uuid() . '.jpg';
$fileLarge = $this->uuid() . '.jpg';
// Crop with Image Intervention
$imageSmall = Cropper::make($request->image)->fit(200, 100, function ($c) {
$c->upsize();
})->encode('jpg', 90);
$imageLarge = Cropper::make($request->image)->fit(500, 300, function ($c) {
$c->upsize();
})->encode('jpg', 90);
// Store on S3
Storage::disk('s3_image')->put($fileSmall, (string) $imageSmall);
Storage::disk('s3_image')->put($fileLarge, (string) $imageLarge);
return [
'image_small' => $fileSmall,
'image_large' => $fileLarge,
];
})
->rules('required')
->disk('s3_image')
->hideFromIndex()
->prunable(),
I'm trying to upload an image using storage folder, and also using traits, but when it comes using Intervention i'm really having trouble where to use it.
Here's the FileUploadTrait.php
public function uploadImage($image) {
if ($image) {
$image_name = $image->store('public');
$name = explode("/", $image_name);
$img_name = $name[count($name) - 1];
return $img_name;
}
return null;}}
ProjectsControler.php
public function store(Request $request, Project $project)
{
$this->validate($request, array(
'image' =>'required|image|dimensions:min_width=800,min_height=600'
));
if ($request->hasfile('image')) {
$img_name= $this->uploadImage($request->image);
$image_resize = Image::make($request->image);
$image_resize->resize(800, 600);
}
$projects = Project::create(
array_merge(
$request->except('image', '_token'),
["image"=>$img_name ?? null]
)
);
return redirect('my/path');
}
the image gets uploaded but not resized.
After upload and resizing you have also to save the image to a given destination.
if ($request->hasfile('image')) {
$img_name= $this->uploadImage($request->image);
$image_resize = Image::make($request->image);
$image_resize->resize(800, 600)->save('Your Path');
}
You’re not saving your new resized image.
$image_resize->save();
I am trying to upload a file using a queue(bean) in laravel but I get this error: Serialization of 'Illuminate\Http\UploadedFile' is not allowed
My code is:
protected $file;
protected $Id;
public function __construct($file,$Id)
{
$this->file = $file
$this->Id = $Id;
}
public function handle()
{
$qFile = $this->file;
$qId = $this->Id;
$s3 = Storage::disk('s3');
$extension = $qFile->guessExtension();
$filename = uniqid().'.'.$extension;
//Create and resize images
$image = Image::make($qFile)->resize(null, 600, function ($constraint) {
$constraint->aspectRatio();
});
$image->encode($extension);
$imageLarge = Image::make($qFile)->resize(null, 800, function ($constraint) {
$constraint->aspectRatio();
});
$imageLarge->encode($extension);
// upload image to S3
$s3->put("images/{$qId}/main/".$filename, (string) $image, 'public');
$s3->put("images/{$qId}/large/".$filename, (string) $imageLarge, 'public');
// make image entry to DB
File::create([
'a_f_id' => $qId,
'file_name' => $filename,
]);
}
But if I remove:
protected $file;
protected $Id;
I dont get the error
You can’t pass an uploaded file instance to a job. You need to write it to disk somewhere, and then retrieve it when handling the job.