Call to a member function extension() on string - php

I have tried to upload the image using Postman and the image is stored in the preferred directory and the full path is stored in database but i am getting the error response
"message": "Call to a member function extension() on string",
here is my code
public function store(AvatarUploadRequest $request, UserService $userService) {
$user = $request->user();
try {
$file = $request->file('avatar');
$file = url("/avatars") . "/" . $user->uuid . ".jpg";
$destinationPath = "avatars";
$user->avatar = $request->file('avatar')->move($destinationPath, $file)
->getClientOriginalExtension();
$user->avatar = $file;
$user->save();
$userService->updateAvatar($user, $file);
}
catch (\Exception $e) {
return jsonApiResponse([
'avatar' => $e->getMessage(),
], 422);
}
return jsonApiResponseWithData($user, 201);
}

I was getting the same error, after 2 hours I realized I had missed:
enctype="multipart/form-data" in the form

You have to add
enctype="multipart/form-data" - in the form, so you can use function like extension() or validator like
"mimes : png , jpg , jpeg"

Remove this line (it seems you do not use it anyway):
->getClientOriginalExtension();
So this should work:
public function store(AvatarUploadRequest $request, UserService $userService) {
$user = $request->user();
try {
$file = $request->file('avatar');
$file = url("/avatars") . "/" . $user->uuid . ".jpg";
$destinationPath = "avatars";
$user->avatar = $request->file('avatar')->move($destinationPath, $file);
$user->avatar = $file;
$user->save();
$userService->updateAvatar($user, $file);
} catch (\Exception $e) {
return jsonApiResponse([
'avatar' => $e->getMessage(),
], 422);
}
return jsonApiResponseWithData($user, 201);
}

Related

Laravel Undefined variable: file

I have a small app to sell online courses.
Everytime I reset my migrations by doing php artisan migrate:reset, I get this error if I try to update a field in my Ecourses edit blade file.
Here's my controller
public function update(Request $request, $id)
{
$slugify = new Slugify();
$this->validate($request, [
'name' => 'required',
'price' => 'nullable',
'category_id' => 'required',
'level_id' => 'required',
'subtitle' => 'required',
'description' => 'required',
'video_link' => 'required',
'document' => 'nullable|file',
'status' => 'required|integer'
]);
$ecourse = Ecourse::findOrFail($id);
$ecourse->name = $request->name;
$ecourse->slug = $slugify->slugify($request->name);
$ecourse->price = $request->price;
$ecourse->status = $request->status;
$ecourse->description = $request->description;
$ecourse->subtitle = $request->subtitle;
$ecourse->video_link = $request->video_link;
$ecourse->category_id = $request->category_id;
$ecourse->level_id = $request->level_id;
$document = $request->file('document');
if ($request->hasFile('document')) {
$documentFullname = $document->getClientOriginalName();
$documentName = pathinfo($documentFullname, PATHINFO_FILENAME);
$extension = $document->getClientOriginalExtension();
$file = time() . '_' . $documentName . '.' . $extension;
$document->storeAs('public/ecourses-files/', $file );
}
$fileToDelete = 'public/ecourses-files'. '/' . $ecourse->document;
if (Storage::exists($fileToDelete)) {
Storage::delete($fileToDelete);
}
$ecourse->document = $file;
$ecourse->save();
return redirect()->route('admin.ecourses.index')->with('success','Formation mise à jour');
}
The error is due to this line $ecourse->document = $file; and to make it work I have to comment it, update my Ecourse blade and then uncomment it.
I really don't know what's happening here...
Any help or explanation would be appreciated.
Thanks and take care.
Well it looks like that $request->hasFile('document') return false in this case this block of code will never run
if ($request->hasFile('document')) {
$documentFullname = $document->getClientOriginalName();
$documentName = pathinfo($documentFullname, PATHINFO_FILENAME);
$extension = $document->getClientOriginalExtension();
$file = time() . '_' . $documentName . '.' . $extension;
$document->storeAs('public/ecourses-files/', $file );
}
So there is no variable $file is defined, to solve this you can do
$file = null;
if ($request->hasFile('document')) {
$documentFullname = $document->getClientOriginalName();
$documentName = pathinfo($documentFullname, PATHINFO_FILENAME);
$extension = $document->getClientOriginalExtension();
$file = time() . '_' . $documentName . '.' . $extension;
$document->storeAs('public/ecourses-files/', $file );
}
This will solve the problem but in case that column document cannot be null it will give you an error so you you will have to make it required in validation rules and check why $request->hasFile('document') returns false
Alternative solution, check $file with isset(), if not define then define it, as like :
if(!isset($file)){
$file = null;
}
$ecourse->document = $file;
There is an operator for this:
$course->document = $file ?? null;

Laravel Update Method Error

i have a method to update image path to data base but i'm getting this error
ErrorException in DriversController.php line 296:
Attempt to assign property of non-object
in my controller
public function updateDriver(Request $request, $id)
{
$driver = Driver::find($id)->update($request->all());
if($request->hasFile('profile-photo')) {
$image_file = $request->file('profile-photo');
$get_image_name = $request['first_name'].$request['phone_number'].'.'.$image_file->getClientOriginalExtension();
$image_name = preg_replace('/\s+/', '', $get_image_name);
$s3 = \Storage::disk('s3');
$filePath = '/drivers/' . $image_name;
$s3->put($filePath, file_get_contents($image_file), 'public');
$driver->profile_photo = $image_name; //this is ware the error line 296
$driver->save();
}
return redirect()->back()->with('message', 'Driver updater successfully');
}
Thank you
$driver will be a Boolean (I believe) after the update.
Try:
$driver = Driver::find($id);
$driver->update($request->all());
You can update your code like :
public function updateDriver(Request $request, $id)
{
$driver = Driver::find($id)->update($request->all());
if($request->hasFile('profile-photo')) {
$image_file = $request->file('profile-photo');
$get_image_name = $request['first_name'].$request['phone_number'].'.'.$image_file->getClientOriginalExtension();
$image_name = preg_replace('/\s+/', '', $get_image_name);
$s3 = \Storage::disk('s3');
$filePath = '/drivers/' . $image_name;
$s3->put($filePath, file_get_contents($image_file), 'public');
$driver = Driver::find($id)->update(array('profile_photo'=>$image_name));
}
return redirect()->back()->with('message', 'Driver updater successfully');
}

Laravel image upload validation

I am trying to validate uploaded files using laravel validation but am having issues.
Here is my code:
$this->validate($request, [
'image' =>'mimetypes:image/jpeg,image/png,image/gif',
]);
$avatar = $request->file('image');
$fileName = time(). '.' . $avatar->getClientOriginalExtension();
Image::make($avatar)->resize(300,300)->save( public_path('uploads/avatar/' . $fileName));
$user = Auth::user();
$user->avatar = $fileName;
$user->save();
The issue is when I use a bmp file, I get this error:
Gd error
I am using the Intervention image package. I would rather not switch to the imagick driver.
Any ideas?
Looking at the Intervention package code, you can see two implementations to the processBmp function:
Intervention/Image/Gd/Encoder.php:
protected function processBmp()
{
throw new \Intervention\Image\Exception\NotSupportedException(
"BMP format is not supported by Gd Driver."
);
}
Intervention/Image/Imagick/Encoder.php:
protected function processBmp()
{
$format = 'bmp';
$compression = \Imagick::COMPRESSION_UNDEFINED;
$imagick = $this->image->getCore();
$imagick->setFormat($format);
$imagick->setImageFormat($format);
$imagick->setCompression($compression);
$imagick->setImageCompression($compression);
return $imagick->getImagesBlob();
}
So I think it's safe to say that you can't do it with the GD driver, only with imagick.
Simply use "intervention/image": "~2" or change your driver to Imagick. It is a known issue that GD does not natively support BMP. You can check the issue page on github for details.
Why you don`t use Laravel custom rule for image image?
$this->validate($request, [
'image' =>'image',
]);
hope this solution will fix your error, please try with below logic
public function postUpload(Request $request)
{
$input = $request->all();
$rules = array(
'uploadFile' => 'image|max:8000'
);
$validation = Validator::make($input, $rules);
if ($validation->fails())
{
return array(
'validation_failed' => true,
'errors' => $validation->errors()->toArray()
);
}
$file = $request->uploadFile;
$destinationPath = 'uploads/img';
// Get real extension according to mime type
$ext = $file->extension();
// Hash processed file name, including the real extension
$hashname = date('H.i.s').'-'.md5($request->_token).'.'.$ext;
$upload_success = $request->uploadFile->storeAs($destinationPath, $hashname);
Image::configure(array('driver' => 'imagick'));
$img = Image::make(storage_path() . '/app/uploads/img/' . $hashname);
$img->resize(230, null, function ($constraint) {
$constraint->aspectRatio();
});
$img->save(storage_path() . '/app/uploads/lowres/' .$hashname ,80);
$user_image = new User_images();
$user_image->id_user = Auth::user()->id;
$user_image->handler = $hashname;
$user_image->save();
return array('status' => 'success','message'=> 'Image has been uploaded successfully','file_path'=>'/uploads/'.$hashname);

Laravel - Pass uploaded filename to new function

I'm using Laravel 5.3 and need to upload an xml file and then submit the contents to an api. The client wants it as 2 buttons/user functions where the user should first upload the file and then with a second click submit the contents.
The uploading is working fine and the xml reading and submitting to api is also working properly. I just can't get my upload controller to pass the filename over to the submitting controller. There is no need to store the filename for future use and the processes will follow each other - ie user will upload one file and submit, then upload next file and submit.
Any help would be highly appreciated
upload function:
public function handleUpload(Request $request)
{
$file = $request->file('file');
$allowedFileTypes = config('app.allowedFileTypes');
$rules = [
'file' => 'required|mimes:'.$allowedFileTypes
];
$this->validate($request, $rules);
$fileName = $file->getClientOriginalName();
$destinationPath = config('app.fileDestinationPath').'/'.$fileName;
$uploaded = Storage::put($destinationPath, file_get_contents($file->getRealPath()));
if($uploaded) {
$file_Name = ($_FILES['file']['name']);
}
return redirect()->to('/upload');
}
submit function:
public function vendorInvoice()
{
$fileName = $file_Name;
$destinationPath = storage_path('app/uploads/');
$xml = file_get_contents($destinationPath.$fileName);
$uri = "some uri";
try {
$client = new Client();
$request = new Request('POST', $uri, [
'Authorization' => '$username',
'ContractID' => '$id',
'content-type' => 'application/xml'
],
$xml);
$response = $client->send($request);
}
catch (RequestException $re) {
//Exception Handling
echo $re;
}
}

Zend\File\Transfer\Adapter\Http on receive : error "File was not found" with jQuery File Upload

Here is already two questions about this problem
Zf2 file upload by jQuery File Upload - file was not found
Can't get blueimp / jQuery-File-Upload and ZF2 running
without ansers. And i'm create issue on ZF2 with code examples.
github.com/zendframework/zf2/issues/6291
And also have request from another developer on my email with question, how to implement jQuery File Upload with ZF2.
github.com/blueimp/jQuery-File-Upload
So, there is real problem for many peple, and no any manuals, no answers.
Please, before send me to read documentation, notice, that i'm spend many hours on problem and already read all documentation and not only i'm have this problem.
Please, write manual with code examples, like How to implement it. Or just answer, why we have this error and how to resolve it?
There i'm copy my example from ZF2 issue.
I'm try use jQuery-File-Upload
Just copy standard tpl, include css and scrypts and it's work, send files to my controller.
But controller doesn't work.
Here is my code
public function processjqueryAction()
{
$request = $this->getRequest();
$response = $this->getResponse();
$jsonModel = new \Zend\View\Model\JsonModel();
if ($request->isPost()) {
try {
$datas = [];
$datas['files'] = [];
$uploadPath = $this->getFileUploadLocation();
$uploadFiles = $this->params()->fromFiles('files');
// throw new \Exception(json_encode("FILES " . serialize($_FILES)));
// Сохранение выгруженного файла
$adapter = new \Zend\File\Transfer\Adapter\Http();
$adapter->setDestination($uploadPath);
$adapter->setValidators(array(
new \Zend\Validator\File\Extension(array(
'extension' => array('jpg', 'jpeg', 'png', 'rtf')
)
),
// new \Zend\Validator\File\Upload()
));
if (!$adapter->isValid()) {
throw new \Exception(json_encode("!isValid " . implode(" ", $adapter->getMessages())));
}
$files = $adapter->getFileInfo();
// throw new \Exception(json_encode($files));
foreach ($files as $file => $info) {
// throw new \Exception(json_encode($info));
$name = $adapter->getFileName($file);
// file uploaded & is valid
if (!$adapter->isUploaded($file)) {
throw new \Exception(json_encode("!isUploaded") . implode(" ", $adapter->getMessages()));
continue;
}
if (!$adapter->isValid($file)) {
throw new \Exception(json_encode("!isValid " . implode(" ", $adapter->getMessages())));
continue;
}
// receive the files into the user directory
$check = $adapter->receive($file); // this has to be on top
if (!$check) {
throw new \Exception(json_encode("! receive" . implode(" ", $adapter->getMessages())));
}
/**
* "name": "picture1.jpg",
"size": 902604,
"url": "http:\/\/example.org\/files\/picture1.jpg",
"thumbnailUrl": "http:\/\/example.org\/files\/thumbnail\/picture1.jpg",
"deleteUrl": "http:\/\/example.org\/files\/picture1.jpg",
"deleteType": "DELETE"
*/
$fileclass = new stdClass();
// we stripped out the image thumbnail for our purpose, primarily for security reasons
// you could add it back in here.
$fileclass->name = $name;
$fileclass->size = $adapter->getFileSize($name);
$fileclass->type = $adapter->getMimeType($name);
$fileclass->deleteUrl = '/uploads/delete';
$fileclass->deleteType = 'DELETE';
//$fileclass->error = 'null';
$fileclass->url = '/';
$datas['files'][] = $fileclass;
}
$response->getHeaders()->addHeaders(array(
'Pragma' => 'no-cache',
'Cache-Control' => 'private, no-cache',
"Content-Type" => 'application/json'
));
// return $response->setContent(json_encode(array('files' => $files)));
return $response->setContent(json_encode($datas));
} catch (\Exception $e) {
return $response->setContent(json_encode($e->getMessage()));
}
}
return $jsonModel;
}
Sorry for debug code, but with it you can see, i'm try hard to make it work, over 3 hours.
Error is
"File 'CIMG0042.JPG' was not found"
When i'm call $adapter->isValid()
Or when call it with file name, same error.
Path, where files uploaded, is correct and writable. $_FILES array is exist and valid.
Here is $_FILES json
FILES a:1:{s:5:\"files\";a:5:{s:4:\"name\";a:1:{i:0;s:28:\"52876065d17dce0a7472e5d6.jpg\";}s:4:\"type\";a:1:{i:0;s:10:\"image\/jpeg\";}s:8:\"tmp_name\";a:1:{i:0;s:14:\"\/tmp\/phpmfT2mB\";}s:5:\"error\";a:1:{i:0;i:0;}s:4:\"size\";a:1:{i:0;i:82640;}}}
And result of $files = $adapter->getFileInfo();
"{"files_0_":{"name":"52876065d17dce0a7472e5d6.jpg","type":"image\/jpeg","tmp_name":"\/tmp\/phpF6VoO9","error":0,"size":"82640","options":{"ignoreNoFile":false,"useByteString":true,"magicFile":null,"detectInfos":true},"validated":false,"received":false,"filtered":false,"validators":["Zend\\Validator\\File\\Upload","Zend\\Validator\\File\\Extension"],"destination":"\/home\/seyfer\/www\/zend2-tutorial.me\/module\/Users\/config\/..\/..\/..\/data\/uploads"}}"
isUploaded passes, but isValid not.
What i'm doing wrong?
Documentation say this
Zend_File_Transfer has been deprecated in favor of using the standard ZF2 Zend\Form and Zend\InputFilter features.
Maybe it's mean, that Form need to be used for file uploading in any way?
UPD 25.05.14
Now i'm add form
class UploadJqueryForm extends BaseForm
{
public function __construct()
{
parent::__construct(__CLASS__);
$this->setAttribute('method', 'post');
$this->setAttribute('enctype', 'multipart/form-data');
$this->init();
}
public function init()
{
$fileupload = new Element\File('files');
$fileupload->setLabel("files");
$fileupload->setAttribute('multiple', 'multiple');
$this->add($fileupload);
$button = new Element\Button('start');
$button->setAttribute("type", 'submit');
$button->setValue("Start upload")->setLabel("Start upload");
$this->add($button);
$button = new Element\Button('cancel');
$button->setAttribute("type", 'reset');
$button->setValue("Cancel upload")->setLabel("Cancel upload");
$this->add($button);
$button = new Element\Button('delete');
$button->setAttribute("type", 'button');
$button->setValue("Delete")->setLabel("Delete");
$this->add($button);
$checkbox = new Element\Checkbox('toggle');
$checkbox->setValue("Toggle")->setLabel("Toggle");
$checkbox->setAttribute("required", "");
$this->add($checkbox);
}
}
Use it
public function processjqueryAction()
{
$form = new \Users\Form\UploadJqueryForm();
$request = $this->getRequest();
$response = $this->getResponse();
$jsonModel = new \Zend\View\Model\JsonModel();
try {
if ($request->isPost()) {
$data = array_merge_recursive(
$this->getRequest()->getPost()->toArray(), $this->getRequest()->getFiles()->toArray()
);
// throw new \Exception(json_encode("data " . serialize($data)));
$form->setData($data);
if ($form->isValid()) {
$datas = [];
$datas['files'] = [];
$uploadPath = $this->getFileUploadLocation();
// $uploadFiles = $this->params()->fromFiles('files');
// throw new \Exception(json_encode("FILES " . serialize($_FILES)));
// Сохранение выгруженного файла
$adapter = new \Zend\File\Transfer\Adapter\Http();
$adapter->setDestination($uploadPath);
$adapter->setValidators(array(
new \Zend\Validator\File\Extension(array(
'extension' => array('jpg', 'jpeg', 'png', 'rtf')
)
),
));
if (!$adapter->isValid()) {
throw new \Exception(json_encode("!isValid " . implode(" ", $adapter->getMessages())));
}
$files = $adapter->getFileInfo();
// throw new \Exception(json_encode($files));
foreach ($files as $file => $info) {
// throw new \Exception(json_encode($info));
$name = $adapter->getFileName($file);
// file uploaded & is valid
if (!$adapter->isUploaded($file)) {
throw new \Exception(json_encode("!isUploaded") . implode(" ", $adapter->getMessages()));
continue;
}
if (!$adapter->isValid($file)) {
throw new \Exception(json_encode("!isValid " . implode(" ", $adapter->getMessages())));
continue;
}
// receive the files into the user directory
$check = $adapter->receive($file); // this has to be on top
if (!$check) {
throw new \Exception(json_encode("! receive" . implode(" ", $adapter->getMessages())));
}
/**
* "name": "picture1.jpg",
"size": 902604,
"url": "http:\/\/example.org\/files\/picture1.jpg",
"thumbnailUrl": "http:\/\/example.org\/files\/thumbnail\/picture1.jpg",
"deleteUrl": "http:\/\/example.org\/files\/picture1.jpg",
"deleteType": "DELETE"
*/
$fileclass = new stdClass();
// we stripped out the image thumbnail for our purpose, primarily for security reasons
// you could add it back in here.
$fileclass->name = $name;
$fileclass->size = $adapter->getFileSize($name);
$fileclass->type = $adapter->getMimeType($name);
$fileclass->deleteUrl = '/uploads/delete';
$fileclass->deleteType = 'DELETE';
//$fileclass->error = 'null';
$fileclass->url = '/';
$datas['files'][] = $fileclass;
}
$response->getHeaders()->addHeaders(array(
'Pragma' => 'no-cache',
'Cache-Control' => 'private, no-cache',
"Content-Type" => 'application/json'
));
return $response->setContent(json_encode($datas));
} else {
throw new \Exception(json_encode("!isValid form" . serialize($form->getMessages())));
}
}
} catch (\Exception $e) {
return $response->setContent(json_encode($e->getMessage()));
}
return $jsonModel;
And still get error
File '24866-fu-blyad-otvratitelno.jpg' was not found
Also I tried with InputFilter
class UploadJqueryFilter extends InputFilter implements
InputFilterAwareInterface
{
public function __construct()
{
$this->getInputFilter();
}
public function getInputFilter()
{
$toggle = new Input('toggle');
$toggle->setRequired(FALSE);
$this->add($toggle);
$files = new \Zend\InputFilter\FileInput('files');
$files->setRequired(TRUE);
$files->getValidatorChain()->attach(new Validator\File\UploadFile);
$files->getFilterChain()->attach(new \Zend\Filter\File\RenameUpload(array(
'target' => __DIR__ . '/../../../../../../tmpuploads/tmp',
'randomize' => true,
)));
$this->add($files);
return $this;
}
public function setInputFilter(InputFilterInterface $inputFilter)
{
return false;
}
}
And have same error.
I had this problem too. Wasting several hours before found the problem. Turn out it's because the name attribute for input tag cannot be set as 'files'.
So this is a no:
<input id="files" type="file" name="files" data-url="/upload-action" />
Changing the name attribute to any string other than files such as file will solve this problem.
<input id="files" type="file" name="file" data-url="/upload-action" />
I see from $_FILES that you had set name as files. Try changing that.
Make sure you update the reference you made in your controller too.

Categories