I'm trying to learn to an process image form that uploads images to a database and lets users view the image on the website, this is done using Laravel 4. I must have some sort of bug, because the view doesn't have any errors, but when I select an image to upload and hit the "save" button on my form, nothing happens other than it looks like the form has been refreshed because the file is gone.
Routes
// This is for the get event of the index page
Route::get('/', array(
'as' => 'index_page',
'uses' => 'ImageController#getIndex'
));
// This is for the post event of the index page
Route::post('/', array(
'as' => 'index_page_post',
'before' => 'csrf',
'uses' => 'ImageController#postIndex'
));
ImageController.php
class ImageController extends BaseController {
public function getIndex()
{
// Let's first load the form view
return View::make('tpl.index');
}
public function postIndex()
{
// Let's validate the form first with the rules which are set at the model
$input = Input::all();
$rules = Photo::$upload_rules;
$validation = Validator::make($input, $rules);
// If the validation fails, we redirect the user to the index page, with errors
if ($validation->passes()) {
// If the validation passes, we upload the image to the database and process it
$image = Input::file('image');
// This is the original uploaded client name of the image
$filename = $image->getClientOriginalName();
// Because Symfony API does not provide filename
// without extension, we will be using raw PHP here
$filename = pathinfo($filename, PATHINFO_FILENAME);
// We should salt and make an url-friendly version of the file
$fullname = Str::slug(Str::random(8) . $filename) . '.' .
$image->getClientOriginalExtension();
// We upload the image first to the upload folder, then
// get make a thumbnail from the uploaded image
$upload = $image->move
(Config::get('image.upload_folder'), $fullname);
Image::make(Config::get('image.thumb_folder').'/'.$fullname)
->resize(Config::get('image.thumb_width'), null, true)
->save(Config::get('image.thumb_folder').'/'.$fullname);
// If the file is now uploaded we show a success message
// otherwise, we show an error
if ($upload) {
// image is now uploaded, we first need to add column to the database
$insert_id = DB::table('photos')->insertGetId(
array(
'title' => Input::get('title'),
'image' => $fullname
)
);
// Now we redirect to the image's permalink
return Redirect::to(URL::to('snatch/'.$insert_id))
->with('success', 'Your image is uploaded successfully!');
}
else {
// Image cannot be uploaded
return Redirect::to('/')->withInput()
->with('error', 'Sorry, the image could not be uploaded.');
}
}
else {
return Redirect::to('/')
->withInput()
->withErrors($validation);
}
}
Image Model
class Photo extends Eloquent {
// the variable that sets the table name
protected $table = 'photos';
// the variable that sets the table name
protected $fillable = array('title', 'image');
// the timestamps enabled
public $timestamps = true;
// Rules of the image upload form
public static $upload_rules = array(
'title' => 'required|min:3',
'image' => 'required|image'
);
}
The view for the form
#extends('frontend_master')
#section('content')
{{ Form::open(array('url' => '/', 'files' => true )) }}
{{ Form::text('title', '', array(
'placeholder' => 'Please insert your title here')) }}
{{ Form::file('image') }}
{{ Form::submit('save', array('name' => 'send')) }}
{{ Form::close() }}
#stop
Let me know if you can find any bugs, I'm pretty sure something must be going wrong in my ImageController#postIndex
Thanks for any insights
2 things you need to check out.
1st off, once you updated your composer.json to include the Intervention/Image package. you should run composer dump-autoload to refresh the autoload file.
2ndly, there's a logical error in your controller.
Image::make(Config::get('image.thumb_folder').'/'.$fullname)
->resize(Config::get('image.thumb_width'), null, true)
->save(Config::get('image.thumb_folder').'/'.$fullname);
should be
Image::make(Config::get('image.image_folder').'/'.$fullname)
->resize(Config::get('image.thumb_width'), null, true)
->save(Config::get('image.thumb_folder').'/'.$fullname);
because you've already moved the image file to image_folder with the code below:
$upload = $image->move
(Config::get('image.upload_folder'), $fullname);
Hope this helps.
Related
i am trying to update the image of profil ,because to user at the beginning it creates account without image, after it goes the update, so i store the image in root /aswakfolder/public/storage/profiles and i insert image link in db profiles/nameimage.jpeg, i created a function in helpers.php file to display the image its work very will, the problem here is that I do not understand the helpers function, and it does not meet my needs, my need is when image upload and exists it displays my image if not it displays image not-found.jpeg,in my case it always displays not-found.jpeg.
stock image in my folder, and url image insert in db very well.
UsersController.php
public function update(Request $request, $id)
{
$user=User::find($id);
if($request->hasFile('image'))
{
$image = $request->file('image');
$path = $request->image->store('profiles');
$user->image = $path;
}
$request->image = $user->image;
$user->id = Auth::user()->id;
$user->update([
$user->name => $request->name,
$user->email => $request->email,
$user->telephone => $request->telephone,
$user->daten => $request->daten,
$user->country_id=> $request->country_id,
$user->state_id => $request->state_id,
$user->city_id => $request->city_id,
$user->image => $request->image,
]);
session()->flash('success', 'user updated successfully !!');
return redirect('users');
}
helpers.php
function productImage($path)
{
return $path && file_exists('/aswakfolder/public/storage/'.$path) ? asset('/aswakfolder/public/storage/'.$path) : asset('/aswakfolder/public/storage/not-found.jpg');
}
index.blade.php
<div class="inner" style="background-image: url({{ asset(productImage($users->image)) }})">
Make sure you run the commend php artisan storage:link to create the shortcurt on public/ folder.
Documentation
I have a form to update my news post which have title, content and image upload button at the same page. The image uploader use Kartik FileINput widget for Yii2 applying Ajax method.
This is my actionUpload that processed the AJAX uploading
public function actionUpload($id)
{
$model = $this->findModel($id);
$currentImage=$model->image;
if (Yii::$app->request->isAjax)
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$image = $model->uploadImage();
if($image===false)
{
//echo "image instance is empty";
$model->image = $currentImage;
}
if ($model->validate() && $model->save())
{
if($image !== false)
{
$model->image = $image->basename.'.'.$image->extension;
$image->saveAs('uploads/batam/'.$model->image);
$model->save(false);
return \yii\helpers\Json::encode(array("image" => $model->image,
));
}
}
else
{echo "validation failed";}
}
}
This is my widget file upload filed in my form (note : it's inside the active form)
echo FileInput::widget([
'name' => 'image',
'options'=>[
'multiple'=>false
],
'pluginOptions' => [
'uploadUrl' => Url::to(['news/upload','id'=>$id]),
'uploadExtraData' => [
'id'=>$id,
],
'initialPreview'=>[
Yii::getAlias('#web').'/uploads/batam'.$model->image
],
'initialPreviewAsData'=>true,
'overwriteInitial'=>false,
'maxFileSize'=>2800
]
]);
this is my model rule and uploadImage method
public function rules()
{
return [
[['title', 'content'], 'required'],
[['content'], 'string'],
[['created_at', 'updated_at'], 'safe'],
[['image'], 'file','skipOnEmpty'=>true, 'extensions'=>'jpg,png,jpeg'],
[['title'], 'string', 'max' => 255],
];
}
public function uploadImage() {
$image = UploadedFile::getInstanceByName('image');
if (empty($image)) {
return false;
}
return $image;
}
I have 2 issues here that needs help :
1. The validation rules won't work. I can upload any file with any extension and it's succesfully uploaded and updated in the database
2. The image upload was contained within the active form, so after a successful upload using AJAX, when I press 'update' button, the image won't display. The image field is treated as empty, so the update button behave as if I updated an empty image. In my database the image path of the AJAX-uploaded file of the respected news-id has been succesfully stored and the file is uploaded.
How to solve this? Actually I don't mind if the upload method didn't use AJAX but just the ordinary, single form submit method with post, thus omitting the upload ajax button, but according to Kartik documentary, if I want to use the widget that display the previously stored image, it needs Ajax.
I had looked around some similar question in StackOverflow etc but all of them had the problem with empty image instance in the Ajax call method ( well, I previously faced the same problem, but i had apply the Formdata on my ajax after I researched), while I don't have the problem with the empty instance on ajax call, but empty instance on the normal form submit.
This is my actionUpdate
public function actionUpdate($id)
{
$model = $this->findModel($id);
$image= UploadedFile::getInstanceByName('image');
if ($model->load(Yii::$app->request->post()) && $model->save() ){
var_dump($image);exit();
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
Thanks in advance!
First of all, the reason why the validators are not working is because you are NOT creating the file input widget from the model, you must do it this way in order for your rules in the class model to work:
echo $form->field($model, 'image')->widget(FileInput::classname(), [
'options' => ['accept' => 'image/*'],
]);
Then I don't know how the structure of your database, but my advice for how to handle image uploads. Is, first, to create a public variable inside the class separated from the image field of the database, this public image variable will be the one that will instanciate the widget on the form and also the one with the rules. This way, when you post your form, the image field from the database will not be overwrited.
So, then when you upload using ajax, you will send the id of the object too, and in the upload function once everything is set, you will store the path, or the image, or whatever in the image field of the database.
I have this function where I want to update user background image so I write:
public function updateBg(Request $request)
{
$user = Auth::user();
$this->validate($request, [
'background' => 'image|max:10000',
// validate also other fields here
]);
// checking file is valid.
if (!$request->file('background')->isValid()) return redirect()->back()->withErrors(["background" => "File is corrupt"]);
// file is valid
$destinationPath = public_path().'/images/Custaccounts/'.$user->id; // upload path
$extension = $request->file('background')->getClientOriginalExtension(); // getting image extension
$ran = str_random(5);
$photo = $ran.'.'.$extension;
$request->file('background')->move($destinationPath, $photo); // uploading file to given path
$bg = $user->id.'/'.$photo;
dd($bg);
$user->update(['background' => $bg]);
return Redirect::back();
}
this line wont work: $user->update(['background' => $bg]); dd($bg) give me right string and image is uploaded just I cant update my 'background; field ...
also when I write:
$user->update(['background' => $bg, 'name'=>'John']);
name is updated but background not... at user model background field is fillable of cource
If i understand your problem you are trying to update the bg field form User table.. Your code must work. If not working Try this:-
Remove this :- $user->update(['background' => $bg]);
Update this :- User::where('id',Auth::user()->id)->update(['background' => $bg]);
Hope it helps!
I have this form to edit article and change photo:
<h1>Edit: {{$article->title}}</h1>
<hr>
{!! Form::model($article, ['method'=>'PATCH','files' => true, 'action'=>['ArticlesController#update', $article->id]]) !!}
#include('articles.form',['submitButtonText'=>'Update Article'])
{!! Form::close() !!}
#include('errors.list')
now at Controller I have this function:
public function update($id, Requests\ArticleRequest $request)
{
$photo= 'http://nationaluasi.com/dru/content/hotelIcon.png';
$file = array('photo' => $request->file('photo'));
// setting up rules
$rules = array('photo' => 'required',); //mimes:jpeg,bmp,png and for max size max:10000
// doing the validation, passing post data, rules and the messages
$validator = Validator::make($file, $rules);
if ($validator->fails()) {
// send back to the page with the input data and errors
$photo = 'http://nationaluasi.com/dru/content/hotelIcon.png';
}
else {
// checking file is valid.
if ($request->file('photo')->isValid()) {
$destinationPath = public_path().'/images'; // upload path
$extension = $request->file('photo')->getClientOriginalExtension(); // getting image extension
$photo = str_random(5).'.'.$extension; // renameing image
$request->file('photo')->move($destinationPath, $photo); // uploading file to given path
// sending back with message
}
else {
}
}
$article = Auth::user()->articles()->findOrFail($id);
$article['photo'] = $photo;
$article->update($request->all());
Alert::message('Your auction is updated', 'Wonderful!');
return redirect('auctions');
}
but now when I try to submit uploaded photo I get this result in column photo: C:\wamp\tmp\php21F4.tmp but also image is uploaded into /images folder...
What is the problem here? How to update article... also I want to say that is everything fine when I add article - add photo so on method store everything is the same and work fine...
UPDATE:
I try:
$article = Auth::user()->articles()->findOrFail($id);
$article['photo'] = $photo;
dd($photo);
and everything is fine, photo is uploaded succesfully just i dont update article['photo']... so problem is here:
$article->update($request->all());
But how to solve it? Why article['photo'] is not updated ?
I tried to correct your code, use this.
public function update($id, Requests\ArticleRequest $request)
{
$this->validate($request, [
'photo' => 'required|image|max:10000',
// validate also other fields here
]);
// checking file is valid.
if (!$request->file('photo')->isValid()) return redirect()->back()->withErrors(["photo" => "File is corrupt"]);
// file is valid
$destinationPath = public_path().'/images'; // upload path
$extension = $request->file('photo')->getClientOriginalExtension(); // getting image extension
$filename = str_random(5).'.'.$extension; // give a name to the image
$request->file('photo')->move($destinationPath, $filename); // uploading file to given path
// sending back with message
$article = Auth::user()->articles()->findOrFail($id); //if article id is unique just write Article::findOrFail($id)
$article_fields = $request->except('photo');
$article_fields['photo'] = $filename;
$article->update($article_fields);
Alert::message('Your auction is updated', 'Wonderful!');
return redirect('auctions');
}
I'll assume you're using Laravel 5. I believe the issue is this line:
$article->update($request->all());
The update method expects an array of column and value pairs. Your code above is giving it the original (unmodified) request which doesn't include your new photo location.
With Laravel you can actually get the article object, set the column directly within the object and then save the changes.
Try changing the last few lines of your method to:
$article = Auth::user()->articles()->findOrFail($id); // get the article
$article->photo = $photo; // set the photo column to your new location
$article->save(); // this will save your changes
Alert::message('Your auction is updated', 'Wonderful!');
return redirect('auctions');
Take a look at the Laravel documentation for more explanation.
I want to update a record in my model, and it contains a file field, here is the form code:
<div class="row">
<?php echo $form->labelEx($model,'img'); ?>
<?php echo CHtml::activeFileField($model,'img',array('width'=>25,'lentgh'=>25)); ?>
<?php echo $form->error($model,'img'); ?>
</div>
and here is the update action in the controller:
$model=$this->loadModel($id);
$img = $model->img;
if(isset($_POST['Press']))
{
$model->attributes=$_POST['Press'];
$model->img = $img;
if(isset($_POST['Press']['img'])){
if(!empty ($_POST['Press']['img']))
$model->img = CUploadedFile::getInstance($model, 'img');
So if the user didn't upload an image, the value of img attribute should not be updated and the model should be validated, but I got validation error every time I click on save and the img file filed is empty, so how I can fix this issue ?
Form validations are handeled by the model.
You can set an imagefield of filefield to be allowed to be empty like this in your model.php:
array('image', 'file', 'types'=>'jpg,png,gif',
'maxSize'=>1024 * 1024 * 5,
'allowEmpty' => true),
EDIT:
You can check if the file is empty before overwriting the current value of the object
$imageUploadFile = CUploadedFile::getInstance($model, 'image');
if($imageUploadFile !== null){ // only do if file is really uploaded
$imageFileName = mktime().$imageUploadFile->name;
$model->image = $imageFileName;
}
You can use csenario as:
array('image', 'file', 'types'=>'jpg,png,gif',
'maxSize'=>1024 * 1024 * 5,
'allowEmpty' => false, 'on'=>'insert'),
array('image', 'file', 'types'=>'jpg,png,gif',
'maxSize'=>1024 * 1024 * 5,
'allowEmpty' => true, 'on'=>'update'),
after that it will allow empty field on update
Faced the same issue and here is my solution.
But first I will describe how I work with models.
Basic POST processing
if (Yii::app()->request->getIsPostRequest()) {
$basicForm->attributes = Yii::app()->request->getParam(get_class($basicForm));
if ($basicForm->validate()) {
$logo = CUploadedFile::getInstance($basicForm, "logo");
if (!is_null($logo)) {
try {
// uploads company logo to S3
} catch (\Exception $e) {
// display any kind of error to the user or log the exception
}
}
if ($basicForm->save(false))
$this->refresh();
}
}
and my logo field has rule ["logo", "file", "mimeTypes" => ["image/png", "image/jpeg"], "allowEmpty" => true].
This rule gives me freedom to upload or not to upload the file, BUT if I want to change another form field not changing the file it will empty the model's logo field and my database too.
Problem
File gets empty if form update trying to update another form field, not file
Why it happening?
This happening because file validator expects CUploadedFile type of object when you have string in the model's logo field. String from database where you storing path to logo. And string is not CUploadedFile. And after if ($basicForm->validate()) model resets the logo field to null.
Solution
Own validation rule which will upload/reupload the file if logo is of hype `` and do nothing if logo of basic string type. Here I will put a basic "in-model" validator, it is up to you to move it into separate class, etc.
public function checkFile($attribute, $params)
{
$mimeTypes = isset($params["mimeTypes"]) ?$params["mimeTypes"] :[];
$allowEmpty = isset($params["allowEmpty"]) ?$params["allowEmpty"] :false;
/** #var CUploadedFile $value */
$value = $this->{$attribute};
if (!$allowEmpty && empty($value))
$this->addError($attribute, "{$attribute} can not be empty");
if (!empty($value)) {
if (is_object($value) && CUploadedFile::class === get_class($value) && 0 < sizeof($mimeTypes)) {
if (!is_array($value->type, $mimeTypes))
$this->addError($attribute, "{$attribute} file is of wrong type");
} elseif (!is_string($value)) {
// we can die silently cause this error won't actually ever get to the user in normal use cases
$this->addError($attribute, "{$attribute} must be of type either CUploadedFile or PHP string");
}
}
}
I called it checkFile and then the logo rule becomes ["logo", "checkFile", "mimeTypes" => ["image/png", "image/jpeg"], "allowEmpty" => true],
That is it. Enjoy.
Note: I'm putting this here as an example. Code may not be completely correct, or used as is, all the stuff like that... :)
I'had same problem. In my user model there wos a field containing path to image and i wanted to update model and fileField cleared my images.
So i figured workaround - store field containing path_to_file at start of action "update" in $tmp_variable and if there is no new upload - just set it before save():
public function actionUpdate($id)
{
$request = Yii::app()->request;
$model = $this->loadModel($id, 'YourModel');
$tmpPathToImage = $model->your_path_to_file_in_model;
$yourModelPost = $request->getPost('YourModel');
if (!empty($yourModelPost)) {
$model->setAttributes($yourModelPost);
$fileSource = Yii::getPathOfAlias('webroot.uploads.yourModel');
$imgTmp = CUploadedFile::getInstance($model, 'your_path_to_file_in_model');
if ($imgTmp !== null) {
$imgTmp->saveAs($fileSource.'/'.$imgTmp->name);
$model->your_path_to_file_in_model = '/'.UPLOADS_YOUR_MODEL_FILE_PATH_RELATIVE.'/'.$imgTmp->name;
}
else {
$model->your_path_to_file_in_model = $tmpPathToImage;
}
if ($model->save()) {
$this->redirect(['/admin/yourModel/index']);
}
}
$this->render('update', [
'model' => $model,
]);
}
Hope it helps someone... :)