I'm creating a site using Laravel 4, which allows an admin to upload a large number of images at a time. Currently, I'm able to do just that, where each image is given its own unique ID and put into its own folder named with the same ID.
The problem is that I need the application to also upload a second, resized (smaller) version of the image along with the original. I learned that you must resize an image on the client side, so I'm not sure how I would go about saving the original image, as well as smaller version. The smaller image should be named using the same ID, with some sort of identifier like "-smaller" at the end of the name.
Here's my current front end;
{{ Form::open(array('url' => 'imageUpload', 'files' => true, 'method' => 'post'))}}
<div class="form-group">
<label for="fileToUpload" class="col-sm-2 control-label">Choose All Images</label>
</br>
{{ Form::file('images[]', ['multiple' => true]) }}
</div>
<div class="col-sm-offset-2 col-sm-10">
{{ Form::submit('Add Photos', ['class' => 'btn btn-large btn-primary openbutton'])}}
<!--<button type="submit" class="btn btn-default">Sign in</button> -->
</div>
{{ Form::close() }}
And here's my controller;
$files = Input::file('images');
foreach($files as $file) {
$rules = array(
'file' => 'required|mimes:png,gif,jpeg,txt,pdf,doc,rtf|max:9999999999'
);
$validator = \Validator::make(array('file'=> $file), $rules);
if($validator->passes()){
$id = Str::random(14);
$id = $race . "-" . $id;
$destinationPath = 'raceImages/' . $id;
//$filename = $id;
$filename = $file->getClientOriginalName();
$mime_type = $file->getMimeType();
$extension = $file->getClientOriginalExtension();
$upload_success = $file->move($destinationPath, $id);
);
} else {
return Redirect::back()->with('error', 'I only accept images.');
}
}
This is how I resolved the same problem in my app:
Install this package: https://github.com/Intervention/image
Use this code:
$createnew = new Yourmodelname;
$avatar = Input::file('pic_path');
if (isset($avatar)) { //will process the code only if an image was properly pointed in the form
$image = Input::file('pic_path');
var_dump($image->getRealPath()); // just for error tracking
$filename = $image->getClientOriginalName();
if (Image::make($image->getRealPath())->save('foldername/yourprefix_' . $LastInsertId . '_' . $filename)) { } // foldername is related to your public folder
if (Image::make($image->getRealPath())->widen(200)->save('foldername/thumbs/thumb_yourprefix_' . $LastInsertId . '_' . $filename)) {
}
$createnew->pic_path = 'event_poster_' . $LastInsertId . '_' . $filename;
$createnew->pic_thumb = 'event_poster_thumb_' . $LastInsertId . '_' . $filename;
$createnew->save();
}
Now you have two files: one original (no changes) and a thumbnail scaled proportionally to width 280.
Other resize options you can find in the Intervention docs.
Related
Now I use a simple way to upload images:
if ($request->hasFile("images")) {
$file = $request->file("images");
// Do uploading to Storage
$uploaded = Storage::put($destinationPath. $fileName, file_get_contents($file->getRealPath()));
}
How can I upload multiple files when I have: images[] in HTML form?
Is it possible to do with Storage::put()?
If your form is submitting multiple files under images[] array, you would loop through them accordingly.
It would help if you posted the form html as well.
<?php
$files = $request->file("images");
$uploaded = [];
if($files){
foreach($files as $file) {
$uploaded[] = Storage::put($destinationPath. $fileName, file_get_contents($file->getRealPath()));
}
}
});
In the view (using the LaravelCollective package):
{{ Form::open(['action' => 'MyController#store', 'class' => 'form-horizontal', 'files' => true, 'enctype' => 'multipart/form-data' ]) }}
{{ Form::file('attachments[]', ['class' => 'form-control', 'roles' => 'form', 'multiple' => 'multiple']) }}
{{ Form::close() }}
In the controller:
public function store(Request $request)
{
if (($request->has('attachments'))) {
$files = $request->file('attachments');
$destinationPath = storage_path() . '/app/public/';
foreach ($files as $file) {
$fileName = $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$storeName = $fileName . '.' . $extension;
// Store the file in the disk
$file->move($destinationPath, $storeName);
}
}
}
When I upload an image it set as random numbers like //15215653352.png. But instead I have my images must be precise , and that means I have a folder which has the pictures set organized(digital_1.png,digital_2.png,digital_3.png...)
##The folder of images is in public called imagg##
Inside the productFactory I'm using this :
'image' => 'digital_'.$this->faker->unique()->numberBetween(1,28).'.png',
To add a picture I have this code :
$imageName = Carbon::now()->timestamp.'.'. $this->image->extension();
$this->image->storeAs('imagg',$imageName,'public');
$product->image = $imageName;
The items-component.blade.php:
#foreach ($products as $product)
<!-- grid item #1 -->
<a href="{{route('product.details',$product->slug)}}">
<div id="TEST" class="activities-grid-item bla" style=" background-image: url({{asset('imagg')}}/{{$product->image}}" >
<h1 class="activities-h1">
.
.
.
</a>
$endforeach
the filesystem.php:
'root' => storage_path('app'),
So therefore the images cannot be displayed with those random numbers but they must be named suc has digital_x.png (while x is variable from 1 to 28 , and existed in the imagg folder).
This should work.
try {
$dir = 'folder/to_the_images/'; // path to the images
if (is_dir($dir)) {
$images = glob($dir . '{*.jpg, *.JPG, *.jpeg}');
$imageName = 'digital_' . count($images) + 1 . '.' . $this->image->extension();
$this->image->storeAs('imagg', $imageName, 'public');
$product->image = $imageName;
}
} catch (\Exception $exception) {
die('saving images failed ' . $exception->getMessage());
}
After a succesful file upload, my show.blade doesn't seem to find my images to display.
I've already linked the directory and the image uploads directly to the wished directory.
post Controller
public function store(Request $request)
{
/**
* Validation Rules using Validator class
*/
$rules = [
/*'post_id' => 'required|numeric',*/
'title' => 'required|min:3',
'intro' => 'required|min:3',
'content' => 'required|min:3',
'image.*' => 'image|mimes:jpeg,png,jpg,gif,svg|max:2048'
];
$validator = Validator::make($request->all(),$rules);
if($validator->fails()) {
// dd('validation fail');
return Redirect::back()
->withInput()
->with(
[
'notification' =>'danger',
'message' => 'Something went wrong'
]
)
->withErrors($validator);
}
$post = new Post();
$post->title = $request->input('title');
$post->intro = $request->input('intro');
$post->content = $request->input('content');
$success = $post->save();
/**
* Handle image upload
*/
if($request->hasfile('image') && $success){
$directory = '/post-' . $post->id;
foreach($request->file('image') as $image) {
$name = $image->getClientOriginalName();
$extension = $image ->getClientOriginalExtension();
$fileName = pathinfo($name,PATHINFO_FILENAME) . '-' . time() . '.' . $extension;
$image->storeAs($directory,$fileName,'public');
$image = new Image();
$image->post_id = $post->id;
$image->filename = $fileName;
$image->filepath = $directory;
$image->save();
}
return back()->with([
'notification' => 'succes',
'message' => 'You have created a new post'
]);
}
}
Show blade
#extends('layout')
#section('content')
<div>
<h1 class="title">{{$post->title}}</h1>
<p> {{$post->content}} </p>
<div class="row">
#foreach($post->images as $image)
<div class="col-sm">
<img class="img-fluid" src="{{ asset($image->filepath . '/' . $image->filename) }}" alt="{{ $post->title }}">
</div>
#endforeach
</div>
</div>
<p>Edit</p>
#endsection
when i inspect the element, i get the image's alt which is the $post-> title, but the path seems to be incorrect for some reason.
storeAs function returns path to the stored file relative to the storage. You don't need to concatenate it yourself. Also it can be a problem with a forward slash in the path.
// Store result path to the variable
$path = $image->storeAs($directory,$fileName,'public');
$image = new Image();
$image->post_id = $post->id;
$image->filename = $fileName;
$image->filepath = $path; // Save path returned by the storeAs
$image->save();
Use asset with just that path.
<img class="img-fluid" src="{{ asset($image->filepath) }}" alt="{{ $post->title }}">
Also check your file system configuration. public/storage should be symbolic link to the storage/app/public, otherwise stored files will not be accessible from the web.
give this a try.
<img class="img-fluid" src="src="{{ asset('path/to/image/'. $image->filename) }}"" alt="{{ $post->title }}">
I will rather approve it this way
Get the last inserted post ID
$post_id = post->id;
$image = $request->file('image');
if ($request->hasFile('image'))
{
foreach ($request->image as $img) {
$name = $image->getClientOriginalName();
$extension = $image->getClientOriginalExtension();
$fileName = $name . '-' . time() . '.' . $extension;
if (!file_exists('POST/IMAGE')) //Let check if the path doesn't exist
{
mkdir('POST/IMAGE', 0777 , true);// then create one with read/write permission
}
$image->move('POST/IMAGE',$imagename); // Save the file in this folder
}else {
$imagename = 'dafault.png'; // Optional: if none file selected, the use default file.
}
$image = new Image();
$image->post_id = $post_idid;
$image->filename = $fileName;
//$image->filepath = $directory;// You don't really need the save the file name in your DB
$image->save();
}
return back()->with([
'notification' => 'succes',
'message' => 'You have created a new post'
]);
}
I am building a form that allows users upload more than one file provided they click on the 'Add more files' link. When I upload more than one file, for example, 2 files, I see the 2 files in the folder I store files but in database table, its only the first of the 2 files that is saved on the table. And it is saved twice. For instance, if I upload 3 files, the first of the 3 files is saved 3 times on the table but the 3 individual files I can see in the folder. Whats the problem here?
My view:
<label class="control-label mb-10" for="exampleInputuname_1">Uploads</label>
<input type="file" class="form-control" id="exampleInputuname_1"
name="file[]" required>
<a class="add_more" href="">Add More Files</a>
JQuery
$( function() {
$('.add_more').click(function(e){
e.preventDefault();
$(this).before("<input name='file[]' type='file' class='form-control'/>");
});
});
My controller
foreach ($files as $file) {
$file_extension = $file->getClientOriginalExtension();
$new_name = base64_encode(date('Y-m-d H:i:s') . $file->getClientOriginalName()) . '.' . $file_extension;
$destinationPath = 'uploads/files';
$file->move($destinationPath, $new_name);
$filename = $destinationPath . '/' . $new_name;
$i++;
$uri = Utilities::generateFileRef($i);
File::create([
'uri' => $uri,
'user_id' => $user_id,
'title' => $request->folder_name,
'document' => $filename,
'folder_id' => $folder_id
]);
}
Hi I am trying to upload multiple images using the intervention package but when I start upload one image only gets upload
here is the view
{!! Form::open(array('url'=>'admin/event-gallery', 'method'=>'post', 'files'=>'true')) !!}
{!! Form::label('image', 'Event Image Gallery') !!}
{!! Form::file('image[]', ['multiple']) !!}
{!! Form::hidden('event_id', $event->id) !!}
{!! Form::submit('Add More Images', array('class'=>'btn btn-primary')) !!}
{!! Form::close() !!}
and here is the controller
public function store( Request $request ) {
$event = new EventGallery();
if ( $request->hasFile( 'image' ) ) {
$images = $request->file( 'image' );
foreach ( $images as $image ) {
$event->event_id = $request->event_id;
$filename = time() . '.' . $image->getClientOriginalExtension();
Image::make( $image )->resize( 450, 150 )->save( 'images/events/' . $filename );
Image::make( $image )->fit( 243, 111 )->save( 'images/events/thumbs-' . $filename );
$event->image = $filename;
}
}
$event->save();
Session::flash( 'status', 'Event has been added successfully' );
return Redirect::to( 'admin/events/create' );
}
Edit on how I got it work
First it was the save() outside the foreach loop.
Second I had a very strange issue here when I done with upload I found the images duplicated, and this was cased by this part of the code $filename = time() . '.' . $image->getClientOriginalExtension(); it was because the time() so don't trust the time() when you are uploading multiple files here I replaced it with str_random( 10 ) and every this was OK after that.
if anybody have any comments or suggesting will be happy to hear from him.