How to upload multiple images with base64 in laravel & vue-js - laravel

I have been trying to upload multiple images with base64 but it uploads only the second one.
and Is there any easy way to upload images in larvel-vueJS instead of base 64.
this is the Vue-js method:
updateIMG(e){
// console.log('uploaded');
let file = e.target.files[0]
let reader = new FileReader();
if(file['size'] < 9111775){
reader.onloadend = (file) => {
this.landingform.logo = reader.result;
this.landingform.landingBg = reader.result;
}
reader.readAsDataURL(file)
}else {
swal.fire({
icon: 'error',
title: 'Oops...',
text: 'You are uploading a large fiel!',
footer: 'You are authorized to upload files less than 10MB.'
})
}
the method called like this:
<input type="file" #change="updateIMG" name="logo" class="form-input">
and this is my controller:
public function updateLanding(Request $request)
{
$landnginIMG = LandingImage::whereIn('id', [1]);
if ($request->logo){
$name = time().'.' . explode('/', explode(':', substr($request->logo, 0,
strpos($request->logo, ';')))[1])[1];
\Image::make($request->logo)->save(public_path('img/landing/').$name);
$request->merge(['logo' => $name]);
};
if ($request->landingBg){
$bgname = time().'.' . explode('/', explode(':', substr($request->landingBg, 0,
strpos($request->landingBg, ';')))[1])[1];
\Image::make($request->landingBg)->save(public_path('img/landing/').$bgname);
$request->merge(['landingBg' => $bgname]);
};
$landnginIMG->update([
'logo'=> $request ['logo'],
'landingBg'=> $request ['landingBg'],
]);
return ['message' => 'all is done'];
}

There are a few factors your must follow.
First
Your form should let you select multiple files
Second
Your JavaScript must handle all of those files when selected. Check this line of your code.
// console.log('uploaded');
let file = e.target.files[0]
let reader = new FileReader();
e.target.files[0] is taking the first file. You should loop and go through all files.
let files = e.target.files;
Now, use JavaScript foreach loop and convert each file to base64 and store them on array. Then, send that array to sever.
On the server, do the same. You will receive an array so you should loop through each and convert it back to image and save it.
Thanks.

Pls check if this helps:
Vuejs example of multiple image upload https://picupload.netlify.app/
VueJS code repo https://github.com/manojkmishra/dw_take5
Concerned File- https://github.com/manojkmishra/dw_take5/blob/master/src/components/ImageUploader.vue
PHP[Laravel] part is behind firewall so upload submission will not work outside intranet. Here is the controller function code
public function imagesupload(Request $request){
if (count($request->images)) {
foreach ($request->images as $image) {
$image->store('images');
}
}
return response()->json(["message" => "Done"]);
}

Related

How To upload multiple pictures With laravel and Cloudinary?

Actually I'm on a laravel and reactJs project. I want to upload multiple pictures (album) with laravel and Cloudinary but I didn't find the right solution.
This my db migration file:
public function up()
{
Schema::create('unites', function (Blueprint $table) {
$table->increments('unit_id');
$table->unsignedInteger('building_id');
$table->foreign('building_id')->references('building_id')->on('buildings');
$table->unsignedInteger('floor_id');
$table->foreign('floor_id')->references('floor_id')->on('floors');
$table->string('unit_name',200);
$table->tinyinteger('unit_status');
$table->integer('unit_roomnumber');
$table->string('unit_type',5);
$table->string('unit_pictures');
$table->date('unit_added_date')->format("yyyy-MM-dd");
$table->timestamps();
});
}
An this My function in the controller :
else {
$unit = new Unite();
$unit ->unit_name = $request->input('unit_name');
$unit->building_id = $request->input('building_id');
$unit->floor_id = $request->input('building_id');
$unit->unit_type = $request->input('unit_type');
$unit->unit_status = $request->input('unit_status');
$unit->unit_roomnumber = $request->input('unit_roomnumber');
$unit->unit_added_date = $request->input('unit_added_date');
$images = $request->file('unit_pictures');
$uploaded = [];
foreach ($images as $image) {
error_log('for statement fires.');
Cloudinary::upload($image, null, [
'folder' => '/units',
// 'discard_original_filename' => true,
])->getSecurePath();
return array($uploaded);
}
$unit->unit_pictures=$request->file('unit_pictures');
$unit->save();
return response()->json([
'status' => 200,
]);
I would be very Thankful if anyone of you can help me
foreach ($request->file('images') as $imagefile) {
$uploadedFileUrl = Cloudinary::upload($imagefile->getRealPath())->getSecurePath();
}
The Cloudinary::upload() allows you to process a single asset at one time (see Upload API). For every upload, the response JSON will be returned containing all the information for the newly uploaded asset (see sample response JSON). If you wish to capture the results of every asset, you could collect them within the foreach, for example:
$unit->unit_pictures = $request->file('unit_pictures');
$allUploadApiReponse = array();
foreach ( $unit->unit_pictures=$request->file('unit_pictures') as $imagefile)
{
$uploadedFileUrl = Cloudinary::upload($imagefile->getRealPath(), [ 'folder' => 'Units' ] )->getSecurePath();
array_push($allUploadApiReponse, $uploadedFileUrl);
}
// To check content
print_r($allUploadApiReponse);
$unit->save();`

Importing generated csv from Laravel into Google Sheets

I'm trying to import an automatically generated csv into Google Sheets using this as cell value:
=importData("https://example.com/reports/some-report")
When I try importData on a static file on the server everything works as expected (like =importData("https://example.com/storage/some-static-report.csv") )
..but when I generate the file on the fly () I get a #N/A in the cell; "Resource at url not found." error.
This is the Laravel code to generate the csv:
public function downloadReportsAsCSV(Request $request) {
$list = [];
$list[] = ['timestamp', 'id', 'value'];
// ... fill the list with data here
$callback = function() use ($list) {
$out = fopen('php://output', 'w+');
// Write CSV lines
foreach ($list as $line) {
fputcsv($out, $line);
}
fclose($out);
};
$name = 'somereport.csv';
$headers = [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename='. $name,
];
return response()->stream($callback, 200, $headers);
}
The route to this method is public so authentication is not a problem in this case.
When I call https://example.com/reports/some-report in a browser it downloads the file (as somereport.csv), but somehow Google Sheeds can't handle it the way I expect it to.
Any ideas on how to make this work?
It seems to be working after all, it's just that Google Sheets apparently needed quit some time before updating the field (at least a couple of minutes).
If anyone has any idea how to trigger Google Sheets to update the data immediately I'd sure like to know.

Laravel: How to validate multiple size rules on same file based on mime-type

Hello great people of SO!
I hope you all have a good day
I want to validate uploaded file based on their mime type
if file is an image, maximum size is 2Mb
if file is a video, maximum size is 500Mb
Atm, this is my code snippet
public function upload(Request $request) {
$request->validate([
'file.*' => ['required', 'file', 'mimes:jpg,jpeg,png,mp4', 'max:2048'] // 2 Mb for images / photos, *but how to put maximum size for video?*
]);
...
}
As you can see, I put: max:2048, which is maximum size for an image
I want to allow users, to upload video up to 500Mb
UPDATE
I can separate each file type based on their mimes on JavaScript
// Example: (Some snippet from my code)
var files = Array.prototype.slice.call(event.target.files)
$formData = new FormData
files.forEach((f, i) => {
var fType = f.type.lowerCase()
// or if you want to get file ext,
// use this: f.name.substr(f.name.lastIndexOf('.') + 1, f.name[length - 1])
// 'example_image.jpeg' > 'jpeg'
// 'example_video.mp4' > 'mp4'
// Here, we can validate the files
// Example:
// You can use regex here, but I prefer to use an array of string, so for future update, if I ever want to 'whitelist' new ext, I can easily add them to this array
if (['image/jpeg', 'image/jpg', 'image/png'].indexOf(fType) !== -1) {
// File is an image with format: jpe?g / png
if ((f.size / 1024) < 2048) {
// Image size is less than 2Mb, valid
$formData.append(['image[' + i + ']', f); // f is the file, see forEach above
}
}
if (['video/mp4'].indexOf(fType) !== -1) {
// File is a video
if ((f.size / 1024) < 512000) {
// Video size is less than 500 Mb, valid
$formData.append(['video[' + i + ']'), f);
}
}
// else: error (file is not an image / video)
... // XHR upload call
})
Then, on server side, for validation
// I can separate the uploaded files
public function upload(Request $request) {
// OBVIOUSLY 'this is NOT the best way to do it'
$request->validate([
'image.*' => ['file', 'mimes:jpg,jpeg,png', 'max:2048'],
'video.*' => ['file', 'mimes:mp4', 'max:512000']
]);
..
}
If you want to know which index the error is:
// *NOTE* I'm using Vue & Axios here
Object.entries(exc.response.data.errors).forEach(([e, m]) => {
// Error response would be:
// image.0 => ['error message']
// ...
// video.3 => ['error message']
var errorIndex = parseInt(e.split('.')[1])
// image.0 > ["image", "0"]
errorMsg = m[0]
// Since we stored all previous selected files in an array
console.log(`Error in file index: ${errorIndex}, file name: ${this.upload.files[errorIndex].name}`)
console.log(`Error message: ${errorMsg}`)
// Error in file index [X], file name: hello_there.mp4
// Error: video.X size cannot be more than ... kilobytes (500Mb)
})
But the thing is, I want to do it only with Laravel way
Q: How to put maximum size for video?
Thanks in advance
you can validate based on file mime type like below psudo-code:
public function upload(Request $request) {
$rules = [];
$image_max_size = 1024 * 2;
$video_max_size = 1024 * 500;
foreach($request->file('file') as $index => $file){
if(in_array($file->getMimeType(), ['image/jpg', 'image/jpeg', 'image/png']) {
$rules["file.$index"] = ["max:$image_max_size"];
} else if (in_array($file->getMimeType(), ['video/mp4']){
$rules["file.$index"] = ["max:$video_max_size"];
} else {
// Always non-validating => returns error
$rules["file.$index"] = ['bail', 'mimes:jpg,jpeg,png,mp4'];
}
}
$request->validate($rules);
...
}
I had similar problem and make that solved using this approach.
try this =>
public function upload(Request $request) {
$request->validate([
'file.*' => ['required', 'file', 'mimes:jpg,jpeg,png', 'max:2048'],
'file.mp4' => ['required', 'file', 'mimes:mp4', 'max:512000'] // 500 Mb for video/
]);
}

Attach TCPDF to mail in Laravel

I want to attach pdf generated with tcpdf library without save.
I'm able to attach the pdf generated but it's corrupt.
I search a lot examples but any seems don't work
This my code:
public function index($id) {
$viaje = Viaje::find($id);
$users = User::orderBy('id', 'asc')->get();
// usersPdf is the view that includes the downloading content
$view = \View::make('usersPdf', ['viaje' => $viaje, 'users' => $users]);
$html_content = $view->render();
// Set title in the PDF
PDF::SetTitle("List of users");
PDF::AddPage();
PDF::writeHTML($html_content, true, false, true, false, '');
//PDF::Output('userlist.pdf');
$fileatt = PDF::Output($name='yourfilename.pdf', $dest='E');
$pdf = chunk_split($fileatt);
$contactopro = Contactoviajespro::find($id);
$data = [
'link' => 'http://',
'contacto' => $contactopro->name,
];
Mail::send('emails.notificacion', $data, function($msg) use($pdf) {
$msg->from('administracion#buendialogistica.com', 'Javier');
$msg->to('xavieeee#gmail.com')->subject('Notificación');
$msg->attachData($pdf, 'orden.pdf');
});
return redirect()->route('home')
->with(['message' => 'Email enviado correctamene']);
}
Use "S" to generate pdf and do not do chunk_split(), Laravel will do that. Additionally, if you are using queue() instead of send(), it will fail because of the attachment. To queue, write a job and send with the job queue.

axios/laravel/formdata post request is empty

I want to upload some files, but when i post with axios, my formdata is an empty request in laravel
vuejs: uploader.vue
filesChange(e) {
const fileList = e.target.files;
const formData = new FormData();
if (!fileList.length) return;
for (let i = 0; i < fileList.length; i += 1) {
console.log(fileList[i]);
formData.append('files', fileList[i], fileList[i].name);
}
this.save(formData);
},
output from console, all files are looped and appended to formData
save(formData) {
photosApi.storePhotos(formData, this.galleryId).then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
},
vuejs: photosApi.js
storePhotos(formData, id) {
return axios.post(`api/photo/${id}`, formData);
},
when i inspect my api-call i see this
laravel: api.php
Route::post('/photo/{id}', 'PhotoController#store');
laravel: PhotoController.php
public function store(Request $request, $id)
{
return $request->all();
}
the return of my response is only empty...
what im'doing wrong?
I solved it finally :)
the first problem was this line
formData.append('files', fileList[i], fileList[i].name);
append was always overwriting the last "files" entry... (i thought it was working like push)
so the first fix was
formData.append(`file${i}`, fileList[i], fileList[i].name);
to see the data don't use
return $request->all();
instead use
print_r($request->all());
now you can see something usefull when you inspect your apicall
now it was easy
$data = $request->all();
foreach ($data as $key => $file) {
$file->move('/public/images', $file->getClientOriginalName());
};
all my files are stored in my folder ;)
UPDATE:
I found out, if i write files with "[]" then i get also the data as an array
for (let i = 0; i < fileList.length; i += 1) {
formData.append('files[]', fileList[i], fileList[i].name);
}
And in my controller i get access to my files with this line, but without the "[]"
$files = $request->file('files');

Resources