I want to download a file from the website. But I am getting error while doing that. So lets say user fill in the form and upload cv, it will store in database and I have the file inside my public/uploads/image in laravel. However I want it to be download inside the admin server-side. when admin see the user's list, and click "download" button. It will be able to download the cv. Any help is much appreciate because I just learn about laravel this week. should I create new controller just to download it? can I just use the same controller when user upload their cv? My error message is Missing required parameters for [Route: download] [URI: download/{file}].
ListController.php
public function store(Request $request)
{
$this->validate($request, [
'fullname' => 'required',
'email' => 'required',
'contact' => 'required',
'address' => 'required',
'attachment' => 'required|mimes:pdf,docx,doc|max:2048',
]);
$input = $request->all();
if ($request->has('attachment')) {
$file = $request->file('attachment');
$text = $file->getClientOriginalExtension();
$name = $input['fullname'];
$folder = '/uploads/images/';
$filePath = $folder . $name. '.' . $file->getClientOriginalExtension();
$this->uploadOne($file, $folder, 'public', $name);
}
Form::create($request->all());
return view('form.index');
public function download($file)
{
$file_path = public_path('uploads/images/'.$file);
return response()->download( $file_path);
}
web.php
Route::get('/download/{file}','CandidateController#download')->name('download');
form.blade.php this is the button for the download
<h2 class="font-medium text-base mr-auto">Download CV</h2> <button class="button border items- center text-gray-700 dark:border-dark-5 dark:text-gray-300 hidden sm:flex"> <i data-feather="file" href="{{ route('download',$candidate->file) }}" class="w-4 h-4 mr-2"></i> Download Docs </button>
When it says the missing required parameter, It mostly means the file is not sent.
Try this one:
href="{{ route('download', ['file' => $candidate->file]) }}",
In your controller:
public function download(Request $request) { public_path('uploads/images/'. $request->get('file')) }
Related
I am making a web application in the Laravel Framework. I have written code that saves a image in the database.
Code for saving a image in the database (code in my controller):
public function store(Request $request)
{
$request->validate([
'title' => 'required',
'description' => 'required',
'category_id' => 'required',
]);
$user = request()->user();
$assortment = $user->assortments()->create($request->all());
if($request->hasFile('image') && $request->file('image')->isValid()) {
if($request->hasFile('image') && $request->file('image')->isValid()) {
//dd($request->image->store('images', 'public'));
$assortment->image_path = $request->image->store('images', 'public');
$assortment->save();
//Check what the Storage::url() generates
//dd(Storage::disk('public')->url($assortment->fresh()->image_path));
}
else {
abort(500, "Image not valid");
}
}
if ($request->wantsJson()) {
return response([], 204);
}
return redirect()->route('assortments.show', $assortment->slug)
->with('success','Verzameling is succesvol aangemaakt.');
}
I want my image to be retrieved from my database in the view but I do not know how to go about doing this. I tried things like:
<img src="/images/{{ $imageVariableName }}"> Variables and path are changed
The view I am trying to make my image be retrieved and shown:
<div class="mt-10">
<ul class="md:grid md:grid-cols-2 md:gap-x-8 md:gap-y-10">
#foreach ($assortment->itemCategories as $category)
<li>
<a href="{{ route('categories.show', [$assortment->slug, $category->id]) }}">
<div class="flex px-4 py-5 bg-white shadow overflow-hidden sm:rounded-md sm:px-6">
<div class="flex-shrink-0">
<div class="flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white">
<!-- Heroicon name: globe-alt -->
</div>
</div>
<div class="ml-4">
<h4 class="text-lg leading-6 font-medium text-gray-900">{{ $category->name }}</h4>
</div>
</div>
</a>
</li>
#endforeach
</ul>
</div>
Anyone know how I go about doing this?
EDIT
I also tried:
<img src="{{ Storage::disk('public')->url($assortment->image_path) }}">
But it also returned no image. Just returned:
I inspected the image and it returned the following link:
http://localhost/storage/tmp/phpSX2W3G
EDIT
I know now the problem has to do with my upload controller. The file should not be stored at a temporary path: /storage//tmp/phpL1ZVcx
EDIT 2
The storage link appears to be broken. Get this in my public/storage:
Greetings,
Parsa
you can use
<img src={{Storage::url($assortment->img)}} />
EDIT:
I found out your problem, the problem not in the display but actually in your upload code
if ($request->hasFile('image')) {
$image = $request->file('image'); //request the file
$fileName = md5($image->getClientOriginalName() . microtime()) . '.' . $image->getClientOriginalExtension(); //use md5 for security reasons and get the extension.
$image->storeAs('', $fileName, 'public'); //store the file in the public folder disk.
$assortment->image_path = $fileName;
$assortment->save();
}
should become, because $filename just a temporary upload file it will be delete later, the actual upload path will be return by storeAs
if ($request->hasFile('image')) {
$image = $request->file('image'); //request the file
$fileName = md5($image->getClientOriginalName() . microtime()) . '.' . $image->getClientOriginalExtension(); //use md5 for security reasons and get the extension.
$assortment->image_path = $image->storeAs('', $fileName, 'public'); //store the file in the public folder disk.
$assortment->save();
}
EDIT2: if you are using nginx you need to remove these line
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 365d;
}
You can try the below:
Have included comments in the code with dd() statements to debug - uncomment the dd() statements if you don't get it working to check.
public function store(Request $request)
{
$validated = $request->validate([
'title' => 'required',
'description' => 'required',
'category_id' => 'required',
]);
$user = request()->user();
if(!$user) {
abort(401, 'Unauthenticated');
}
$assortment = $user->assortments()->create($validated);
if($request->hasFile('image') && $request->file('image')->isValid()) {
//dd($request->image->store('images', 'public'));
$assortment->image_path = $request->image->store('images', 'public');
$assortment->save();
//Check what the Storage::url() generates
//dd(Storage::disk('public')->url($assortment->fresh()->image_path));
} else {
abort(422, "Image not valid");
}
if ($request->wantsJson()) {
return response([], 204);
}
return redirect()->route('assortments.show', $assortment->slug)
->with('success','Verzameling is succesvol aangemaakt.');
}
Verify that you have a public disk configured in the config\filesystems.php, something like
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL') . '/storage',
'visibility' => 'public',
],
//And links specified for symlinking when php artisan storage:link is run
'links' => [
public_path('storage') => storage_path('app/public'),
],
Then run
php artisan storage:link
and check in the public folder that there exists a symlinked storage folder
Then in your blade view, you can use
<img src="{{ Storage::disk('public')->url($assortment->image_path) }}" />
//OR
<img src="/storage/{{ $assortment->image_path }}" />
Controller:
if ($request->hasFile('image')) {
$image = $request->file('image');
$assortment->image_path = $image->store('', 'public');
$assortment->save();
}
NB: Laravel by default will create a unique name for a file and manage extension for you - dependent on your use case you may not need to make this filename yourself.
Artisan Command
php artisan storage:link
Generates the correct symlinks for your public storage.
Template
{{ Storage::url($assortment->image_path) }}
Those three things together should work.
Try
<img src="{{ url('storage/images/'.$assortment->image_path) }}"/>
Try a much simplified version:
if ($request->hasFile('image')) {
$path = $request->file('image')->storePublicly('images'); // Store file in public disk & return path
$assortment->image_path = $path; // If you want filename only, use basename($path)
$assortment->save();
}
After that, you can use Storage::disk('public')->url($assortment->image_path) in your view. Using getClientOriginalExtension() and getClientOriginalExtension() probably isn't a good idea since it's not considered a safe value (source). Laravel's store method saves the file and returns the hashed filename with path for you so you don't have to worry about all that :)
Make sure storage symlink is created:
php artisan storage:link
Also make sure post_max_size and upload_max_filesize in your php.ini are set with sufficient amount.
I need to validate my image array as an image and specific image file extensions only. but my request validation to image WONT ALLOW me to use inser nullable values
For example I will add a content and dont want to add images. then the image should contain null that is why i need to have request validation as nullable. But in my experience null value is not allowed and it gives me error why? help me please
here is the error.
The Promotion Image must be an Image
here is my CONTROLLER
public function store(Request $request)
{
$this->validate($request, [
'promotion_image' => 'image|nullable|max:1999'
]);
$promotion = [];
if ($request->has('promotion_image'))
{
//Handle File Upload
foreach ($request->file('promotion_image') as $key => $file)
{
// Get FileName
$filenameWithExt = $file->getClientOriginalName();
//Get just filename
$filename = pathinfo( $filenameWithExt, PATHINFO_FILENAME);
//Get just extension
$extension = $file->getClientOriginalExtension();
//Filename to Store
$fileNameToStore = $filename.'_'.time().'.'.$extension;
//Upload Image
$path = $file->storeAs('public/promotion_images',$fileNameToStore);
array_push($promotion, $fileNameToStore);
}
$fileNameToStore = serialize($promotion);
}
else
{
$fileNameToStore='noimage.jpg';
}
if (count($promotion)) {
$implodedPromotion = implode(' , ', $promotion);
$promotionImage = new Promotion;
$promotionImage->promotion_image = $implodedPromotion;
$promotionImage->save();
return redirect('/admin/airlineplus/promotions')->with('success', 'Image Inserted');
}
return redirect('/admin/airlineplus/promotions')->with('error', 'Something went wrong.');
}
here is my VIEW
{!! Form::open(['action'=>'Admin\PromotionsController#store', 'method' => 'POST','enctype'=>'multipart/form-data', 'name' => 'add_name', 'id' => 'add_name']) !!}
<div class="form-group">
<div class="table-responsive">
<table class="table table-bordered" id="dynamic_field">
<tr>
<td> {{ Form::file('promotion_image[]')}}</td>
<td>{{ Form::button('', ['class' => 'btn btn-success fa fa-plus-circle', 'id'=>'add','name'=>'add', 'style'=>'font-size:15px;']) }}</td>
</tr>
</table>
{{Form::submit('submit', ['class'=>'btn btn-primary', 'name'=>'submit'])}}
</div>
</div>
{!! Form::close() !!}
No need to add nullable attribute in the validation. just change your validation code like this
$this->validate($request, [
'promotion_image.*' => 'image|max:1999'
]);
If you need user must add image input then you can use required validation rule other wise you don't need such thing.
Above code forces user to add file of type image or nothing at all.
I hope you understand and if any explanation needed, feel free to ask.
You need to validate it as an array:
$validator = Validator::make($request->all(), [
'photos.profile' => 'required|image',
]);
Take a look laravel docs
you may want to combine it with sometimes which indicates that the current validation rules will apply only if the field is present.
I need to validate my image array as an image and specific image file extensions only. but my request validation to image WONT ALLOW me to use inser nullable values
For example I will add a content and dont want to add images. then the image should contain null that is why i need to have request validation as nullable. But in my experience null value is not allowed and it gives me error why? help me please
here is the error.
Undefined variable: promotion
here is my CONTROLLER
public function store(Request $request)
{
$this->validate($request, [
'promotion_image' => 'image|nullable|max:1999'
]);
if ($request->has('promotion_image'))
{
//Handle File Upload
$promotion = [];
foreach ($request->file('promotion_image') as $key => $file)
{
// Get FileName
$filenameWithExt = $file->getClientOriginalName();
//Get just filename
$filename = pathinfo( $filenameWithExt, PATHINFO_FILENAME);
//Get just extension
$extension = $file->getClientOriginalExtension();
//Filename to Store
$fileNameToStore = $filename.'_'.time().'.'.$extension;
//Upload Image
$path = $file->storeAs('public/promotion_images',$fileNameToStore);
array_push($promotion, $fileNameToStore);
}
$fileNameToStore = serialize($promotion);
}
else
{
$fileNameToStore='noimage.jpg';
}
if (count($promotion)) {
$implodedPromotion = implode(' , ', $promotion);
$promotionImage = new Promotion;
$promotionImage->promotion_image = $implodedPromotion;
$promotionImage->save();
return redirect('/admin/airlineplus/promotions')->with('success', 'Image Inserted');
}
return redirect('/admin/airlineplus/promotions')->with('error', 'Something went wrong.');
}
here is my VIEW
{!! Form::open(['action'=>'Admin\PromotionsController#store', 'method' => 'POST','enctype'=>'multipart/form-data', 'name' => 'add_name', 'id' => 'add_name']) !!}
<div class="form-group">
<div class="table-responsive">
<table class="table table-bordered" id="dynamic_field">
<tr>
<td> {{ Form::file('promotion_image[]')}}</td>
<td>{{ Form::button('', ['class' => 'btn btn-success fa fa-plus-circle', 'id'=>'add','name'=>'add', 'style'=>'font-size:15px;']) }}</td>
</tr>
</table>
{{Form::submit('submit', ['class'=>'btn btn-primary', 'name'=>'submit'])}}
</div>
</div>
{!! Form::close() !!}
You need to declare $promotion = [] above if ($request->has('promotion_image')), not inside of it.
So:
public function store(Request $request)
{
$this->validate($request, [
'promotion_image' => 'image|nullable|max:1999'
]);
$promotion = [];
if ($request->has('promotion_image'))
{
//Handle File Upload
That is because your selecting file other than image in your form. See the following to restrict user to only upload images.
<input accept=".png, .jpg, jpeg" name="files[]" type="file" multiple>
Not sure but try once
'promotion_image' => 'nullable|mimes:jpeg,jpg,png,gif|max:1999'
I have a form with multiple fields which stores information including an image upload. There is also an edit view:
Route::PUT('/link/{link}', function (Request $request, Link $link) {
$request->validate([
'name' => 'required|max:255',
'title' => 'required|max:255',
'cell' => 'required|max:255',
'tel' => 'required|max:255',
'email' => 'required|max:255',
'website' => 'required|url|max:255',
'location' => 'required|max:255',
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$img = $request->file('image');
$newfilename = $request->name;
$img->move(public_path("/uploads"), $newfilename);
$link->update($request->all());
return redirect('/');
});
The initial submit and edit works fine along with changing the image file name and storing it in the uploads folder.
The path generated being:
public/uploads/exampleFileName.jpg
The problem here is when it comes to displaying the image in the home view. The code below generates a 404 not found with an additional /tmp/ path which I have no idea about where it comes from.
Code in home view:
#foreach ($links as $link)
<div class="link-box">
<h5 class="off-white-txt">Card [# {{ $link->id }}]</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Name: </span>{{ $link->name }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Title: </span>{{ $link->title }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Cell: </span>{{ $link->cell }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Tel: </span>{{ $link->tel }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Email: </span>{{ $link->email }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Website: </span>{{ $link->website }}</h5>
<h5 class="off-white-txt"><span class="pool-blue-txt">Location: </span>{{ $link->location }}</h5>
<img src="{{url('uploads'.$link->image) }}" class="off-white-txt">
</div>
The error message in the console:
GET http://192.168.10.10/uploads/tmp/phpdtnTcw 404 (Not Found)
My question is the following; How could I edit my code to point to the correct path and display the image?
Thank you in advance.
if you are using storage folder to save images then you should use Storage::url
make sure to run command php artisan storage:link
<img src="{{ Storage::url($link->image) }}" class="off-white-txt">
The temporary path you are getting is from the image itself.
Why? Because you are not setting the image new path after moving the image, so the image is stored inside a temp storage.
To simplify it, you have indeed saved the image under public folder, but the image path is still in the temp storage. This is where the image resides. This temp storage is the default path for every UploadedFile object
You need to explicitly set it's path on the Link object, like so:
$link->image = 'my new path';
$link->save();
I think it is because you cannot access the uploads folder from the view.
I would suggest to create a controller that will get your image in the uploads folder and send a image Response. Something like this :
public function showImage($image)
{
if (!Storage::exists($image->name)) {
return false;
}
$file = Storage::get($image->name);
$type = Storage::mimeType($image->name);
$response = Response::make($file, 200)->header("Content-Type", $type);
return $response;
}
Then you just have to call the right route that points to your controller method :
<img src="{{ route('getMyImage', $image) }}" />
This way you can protect easily the files in your uploads folder (for exemple : put middleware or user control functions ...). Otherwise you can do the php artisan storage:link command
These are all valid points although the setup of my framework didn't play well with the suggestions. I have implemented a workaround for now.
This is the updated code in the web controller:
Route::post('/submit', function (Request $request) {
$data = $request->validate([
'name' => 'required|max:255',
'title' => 'required|max:255',
'cell' => 'required|max:255',
'tel' => 'required|max:255',
'email' => 'required|max:255',
'website' => 'required|url|max:255',
'location' => 'required|max:255',
'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);
$img = $request->file('image');
// Storage::disk('public')->put('uploads', $img);
$newfilename = $request->name;
$img->move(public_path("/uploads"), $newfilename);
$link = tap(new App\Link($data))->save();
return redirect('/');
});
This is the updated view code:
<img src="/uploads/{{ $link->name }}" class="user-img">
Thank you very much for all the help!
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.