I have never sent images that were uploaded in a form to emails before, so I'm having a bit of trouble.
I know this line of code: $request->file('image')->move('/', $fileName); won't do anything because of where I'm moving it to, but that's as far as I could get reading these Laravel docs. As a matter of fact, it spits out this error:
Unable to write in the "/" directory
If I were to remove the above code and submit my form, everything works properly but the image fields shows up empty. That leads me to my question:
Where do I move the image to, and how do I get it from that location so that it can be used in the sent email rather than showing a blank spot as if nothing were uploaded?
Here are my files...
index.blade.php (image part of form only):
<div class="form-group">
{!! Form::file('image') !!}
</div>
emails/contact.blade.php (image part only):
<p>
Image: {{ $image }}
</p>
Requests/ContactFormRequest.php:
<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class ContactFormRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required',
'height' => 'required',
'age' => 'required',
'weight' => 'required',
'gender' => 'required',
'email' => 'required|email',
'image' => 'required|mimes:jpeg,jpg,png|max:200px'
];
}
}
Auth/AboutController.php:
<?php namespace App\Http\Controllers;
use App\Http\Requests\ContactFormRequest;
class AboutController extends Controller {
public function create()
{
return view('pages.index');
}
public function store(ContactFormRequest $request)
{
$fileName = "Image";
$request->file('image')->move('/', $fileName);
\Mail::send('emails.contact',
array(
'name' => $request->get('name'),
'height' => $request->get('height'),
'age' => $request->get('age'),
'weight' => $request->get('weight'),
'gender' => $request->get('gender'),
'email' => $request->get('email'),
'image' => $request->get('image')
), function($message)
{
$message->from('example#example.com');
$message->to('example#example.com', 'Admin')->subject('Example Text');
});
return \Redirect::route('/')
->with('message', 'Your application is on its way!');
}
}
if you want to attach a picture to a mail use this:
Mail::send('emails.contact',
array(
'name' => $request->get('name'),
'height' => $request->get('height'),
'age' => $request->get('age'),
'weight' => $request->get('weight'),
'gender' => $request->get('gender'),
'email' => $request->get('email'),
'image' => $filename
), function($message) use($filename)
{
$message->from('example#example.com');
$message->to('example#example.com', 'Admin')->subject('Example Text');
$message->attach('/'.$filename);
});
usually i did this for uploading picture.
//Request File
$file = $request->file('image');
//Destination
$destination = public_path() . '/img/';
//Define the name
$name= "image";
//Get file extension
$extension = $file->getClientOriginalExtension();
//join the name you set with the extension
$filename = $name . '.' . $extension;
//after that move the file to the directory
$file->move($destination, $filename);
If you want to show the image don't forget use (instead of returning its name)
<img src="foo/bar" />
Related
can someone help me, i want to add article with image. image has successfully entered the directory but in the database the name is always D:\xampp\tmp\php......tmp.
I have changed the system file to public.
Controller
public function store(Request $request)
{
//
$validateData = $request->validate([
'title' => 'required|max:255',
'thumbnail' => 'image|file|max:8192',
'slug' => 'required',
'description' => 'required',
]);
if ($request->file('thumbnail')) {
$imageName = time().'.'.$request->file('thumbnail')->getClientOriginalExtension();
$validatedData['thumbnail'] = $request->thumbnail->move(public_path('uploads/article/'), $imageName);
}
//dd($validateData['thumbnail']);
Article::create($validateData);
return redirect('/admin-article')->with('success', 'Data has been successfully added');
}
Try this
if ($request->file('thumbnail')) {
$imageName = time().'.'.$request->file('thumbnail')->getClientOriginalExtension();
$request->thumbnail->move(public_path('uploads/article/'), $imageName);
$validatedData['thumbnail'] = url('uploads/article/'.$imageName);
}
The reason why it's return a path instead of url because you're using public_path instead of url()
Controller Code
public function store(Request $request)
{
$validateData = $request->validate([
'title' => 'required|max:255',
'thumbnail' => 'image|file|max:8192',
'slug' => 'required',
'description' => 'required',
]);
// Check if request has file
if($request->hasFile('thumbnail')){
// Get File
$file = $request->file('thumbnail');
// Get File Extention
$fileGetFileExtension = $file->getClientOriginalExtension();
// Create customized file name
$fileName = Str::random(20).'_'.date('d_m_Y_h_i_s').'.'.$fileGetFileExtension;
// Save File to your storage folder
Storage::disk('public')->put('uploads/article/'.$fileName,File::get($file));
}else{
$fileName = null;
}
$validatedData['thumbnail'] = $fileName;
Article::create($validateData);
return redirect('/admin-article')->with('success', 'Data has been successfully added');
}
Run php artisan storage:link, if not created
In blade you can get your file like this
I hope this helps. :D
thanks for your answer my problem has been solved with code like this, but only the name of the file stored in the database not with the name of the directory.
public function store(Request $request)
{
$validateData = $request->validate([
'title' => 'required|max:255',
'thumbnail' => 'image|file|max:8192',
'slug' => 'required',
'description' => 'required',
]);
$imageName = time().'.'.$request->thumbnail->getClientOriginalExtension();
$request->thumbnail->move(public_path('articles/'), $imageName);
$Article = new Article;
$Article->title = $validateData['title'];
$Article->thumbnail = $imageName;
$Article->slug = $validateData['slug'];
$Article->description = $validateData['description'];
$Article->save();
return redirect('/admin-article')->with('success', 'Data has been successfully added');
}
public function store(Request $request)
{
$this->validate($request, [
'judul' => 'required',
'category_id' => 'required',
'konten' => 'required',
'gambar' => 'required',
]);
$gambar = $request->gambar;
$new_gambar = time().$gambar->getClientOriginalName();
$post = Posts::create([
'judul' => $request->judul,
'category_id' => $request->category_id,
'konten' => $request->konten,
'gambar' => 'public/uploads/posts/'.$new_gambar,
'slug' => Str::slug($request->judul),
'users_id' => Auth::id()
]);
$img = Image::make('public/uploads/',$gambar->getRealPath())->resize(300,
300)->save('public/uploads/', $gambar->getClientOriginalName());
$gambar->move('uploads', $new_gambar);
$post->tags()->attach($request->tags);
return redirect('post');
}
Add enctype in your html form
enctype="multipart/form-data"
And change for this in your controller:
$img = Image::make($request->file('gambar')->getRealPath());
Also check permissions of the directory in which you are uploading the file
make sure form has enctype:
<form class="form" ... enctype="multipart/form-data">
change controller
use Intervention\Image\ImageManagerStatic as Image;
public function store(Request $request)
{
$this->validate($request, [
// 'judul' => 'required',
//if judul column type is varchar need to set max varchar value or less
//varchar max 255, if higer than 255 strings, extra string will be truncated
'judul' => 'required|string|max:200',
// 'category_id' => 'required',
//category should exist
'category_id' => 'required|exists:categories,id',
'konten' => 'required',
// 'gambar' => 'required',
//validating image is successfully uploaded and is image format
'gambar' => 'required|file|image|mimes:jpg,jpeg,png',
//validation for tags, assuming 1 input <select name="tags[]" multiple="multiple"/>
'tags' => 'array',
'tags.*' => 'exists:tags,id'//each value of input select exists in tags table
]);
// $gambar = $request->gambar;
//get the file from <input type="file" name="gambar"/>
$gambar = $request->file('gambar');
$new_gambar = time().$gambar->getClientOriginalName();
//make path to save image: sample public path
$file_path = public_path("uploads/post/{$new_gambar}");
$img = Image::make($gambar)
->resize(300,300)
->save($file_path);
$post = Posts::create([
'judul' => $request->judul,
'category_id' => $request->category_id,
'konten' => $request->konten,
// 'gambar' => 'public/uploads/posts/'.$new_gambar,
//should maake the image first
'gambar' => $file_path,
'slug' => Str::slug($request->judul),
'users_id' => Auth::id() // <- if it is to get current logged in user, use Auth::user()->id
]);
// $gambar->move('uploads', $new_gambar); //let Intervention do this for you
// $post->tags()->attach($request->tags);
//if tags exists (get values frominput select)
$post->tags()->sync($request->input('tags', []));
//$request->input('tags', []) <- if input tags is not null get value, else use empty array
//if route have name e.g Route::get('post', 'PostController#post')->name('post');
//return redirect()->route('post');
return redirect('post');
}
So here it is.
I want to edit a data in database, it work perfectly if I upload an image every time I fill the form. but the problem raised when I edited another data and didn't upload an image instead of filling it with old image data (which is the file in my local) from database which is a string. the image validation makes the error was raised.
here my image validation
'image' => 'image|max:1024'
if I just put it like this 'image' => 'max:1024', it will run well because it wouldn't check if it's an image, but it will generate a problem where user start using edit data function to inject another unwanted code.
here is the update code
use WithFileUploads;
public $productId;
public $title;
public $description;
public $price;
public $image;
public $imageOld;
protected $listeners = [
'editProduct' => 'editProductHandler'
];
public function update()
{
$this->validate([
'title' => 'required|min:3',
'price' => 'required|numeric',
'description' => 'required|max:180',
'image' => 'image|max:1024'
]);
if ($this->productId) {
$product = Product::find($this->productId);
$image = '';
if ($this->image) {
Storage::disk('public')->delete($product->image);
$imageName = \Str::slug($this->title, '-')
. '-'
. uniqid()
. '.' . $this->image->getClientOriginalExtension();
$this->image->storeAs('public', $imageName, 'local');
$image = $imageName;
} else {
$image = $product->image;
}
$product->update([
'title' => $this->title,
'price' => $this->price,
'description' => $this->description,
'image' => $image
]);
$this->emit('productUpdated');
}
}
I'm trying to store an image in my Laravel project, but I'm having an issue. The image is sucessfuly being added to the /public/images folder as its filename, but when the request hits the database, its added as /private/var/tmp/XXXXX. I've tried to set $request->file as the name, but it still posts as the var/temp.
Controller
public function store(Request $request)
{
$rules = [
// 'address' => 'required',
// 'city' => 'required',
// 'postcode' => 'required',
// 'restDesc' => 'required',
// 'telNumb' => 'required',
// 'resWebsite' => 'required',
// 'restDesc' => 'required',
// 'business_id' => 'unique:busprofiles,business_id',
];
$customMessages = ["Message"];
if ($request->hasFile('file')) {
$request->file->store('public/uploads');
$filename = $request->file->getClientOriginalName();
$filesize = $request->file->getClientSize();
$request->file = $request->file->storeAs('public/uploads', $filename);
}
$this->validate($request, $rules, $customMessages);
Busprofile::create($request->all());
return redirect()->route('business.dashboard')
->with('success', 'Profile created successfully');
}
If it helps: return $request->file returns the correct URL.
The problem is in Busprofile::create($request->all());. You do indeed get the original filename with $filename = $request->file->getClientOriginalName(); but your request stays the same.
Create the array for the database entries manually, according to your database needs.
$data = ['filename' => $request->file->getClientOriginalName(),
...,
];
and
Busprofile::create($data);
I have followed different implementation of file/image upload in Yii 2. One of which is from Kartik's widgets, which is in here: http://demos.krajee.com/widget-details/fileinput
In my view, _form.php:
<div class="col-sm-8">
<?php
// A block file picker button with custom icon and label
echo FileInput::widget([
'model' => $model,
'attribute' => 'image',
'options' => ['multiple' => true],
'pluginOptions' => [
'showCaption' => false,
'showRemove' => false,
'showUpload' => false,
'browseClass' => 'btn btn-primary btn-block',
'browseIcon' => '<i class="glyphicon glyphicon-camera"></i> ',
'browseLabel' => 'Upload Receipt'
],
'options' => ['accept' => 'image/*']
]);
?>
</div>
I only showed you a part of my view. That image upload block is accompanied with other fields like Customer Name, Date From and To, Product Name, etc and a Submit button.
I also have models and controllers generated already.
Part of my controller is this:
public function actionCreate()
{
$model = new Invoice();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->inv_id]);
}
else {
return $this->render('create', [
'model' => $model,
]);
}
}
I have not added anything yet in my actionCreate because I still don't have any idea. And in Kartik's file upload demo, there are no controllers involved or shown.
How do I save the URL/path of the image I chose to upload in my database, and save that image locally?
Edit:
Regarding #arogachev's answer, here's what my afterSave looks like in my model, but still the image path is not saved in my db:
public function afterSave($insert, $changedAttributes)
{
if(isset($this->image)){
$this->image = UploadedFile::getInstance($this,'image');
if(is_object($this->image)){
$name = Yii::$app->basePath . 'C:\wamp3\www\basicaccounting\web\uploads'; //set directory path to save image
$this->image->saveAs($name.$this->inv_id."_".$this->image);
$this->image = $this->inv_id."_".$this->image; //appending id to image name
Yii::$app->db->createCommand()
->update('invoice', ['image' => $this->image], 'inv_id = "'.$this->inv_id.'"')
->execute(); //manually update image name to db
}
}
}
Use the below aftersave in your model
public function afterSave($insert, $changedAttributes)
{
if(isset($this->logo)){
$this->logo=UploadedFile::getInstance($this,'logo');
if(is_object($this->logo)){
$path=Yii::$app->basePath . '/images/'; //set directory path to save image
$this->logo->saveAs($path.$this->id."_".$this->logo); //saving img in folder
$this->logo = $this->id."_".$this->logo; //appending id to image name
\Yii::$app->db->createCommand()
->update('organization', ['logo' => $this->logo], 'id = "'.$this->id.'"')
->execute(); //manually update image name to db
}
}
}
replace the above logo with your own attribute. ie. image
Try given below -
In your Controller
if($model->image = UploadedFile::getInstance($model, 'image'))
{
if ($model->upload())
{
// file is uploaded successfully
}
}
In your Model
public function upload()
{
$path = \Yii::$app->params['basepath'];
if (!is_dir($path)) {
$image_path = BaseFileHelper::createDirectory($path,0777,true);
}
$this->image->saveAs($path . date('Y').'/'.date('m').'/'.date('d').'/'.$this->image->baseName . '.' . $this->image->extension);
$this->image = date('Y').'/'.date('m').'/'.date('d').'/'.$this->image->baseName . '.' . $this->image->extension; // Assign image path to store in Database column (image).
return true;
}
Your image will be save on server as "$path . date('Y').'/'.date('m').'/'.date('d').'/'.$this->image->baseName . '.' . $this->image->extension".
and in the database it will be save as "date('Y').'/'.date('m').'/'.date('d').'/'.$this->image->baseName . '.' . $this->image->extension".
In form
<?= $form->field($model, 'images[]')->widget(FileInput::classname(), [
'options' => ['accept' => 'image/*', 'multiple' => true],
'pluginOptions' => [
'previewFileType' => 'image',
'allowedFileExtensions' => ['jpg', 'gif', 'png', 'bmp','jpeg'],
'showUpload' => true,
'overwriteInitial' => true,
],
]);
?>
In Model
public $images;
public function rules()
{
return [
[['name', 'price'], 'required'],
[['price'], 'integer'],
[['images'],'file', 'maxFiles' => 4],
[['name'], 'string', 'max' => 100],
];
}
In Controller
public function actionCreate()
{
$model = new Product();
if ($model->load(Yii::$app->request->post())) {
$model->save();
$file = UploadedFile::getInstances($model, 'images');
foreach ($file as $file) {
$path =Yii::getAlias('#frontend').'/uploads/'.$file->name;
$file->saveAs($path);
}
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
]);
}