jquery multiple ajax file upload loop async with multiple progressbar - javascript

I need to upload multiple files but one each time asynchronous and show progress for each file. For each file i use separate progress bar with class name according to the list index (ie uploadprogress0,uploadprogress1) my code is this:
var i=0
var formData = new FormData();
formData.append('files[]', toUpload[i]);
ajaxloopreq(formData);
var ajaxloopreq = function (formData) {
$.ajax({
xhr: function () {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener('progress', function (e) {
if (e.lengthComputable) {
var percentComplete = e.loaded / e.total;
elem.find('.uploadprogress' + i).css({
width: percentComplete * 100 + '%'
});
}
}, false);
return xhr;
},
async: true,
type: 'POST',
data: formData,
cache:false,
contentType: false,
processData: false,
url: '',
success:function(data){
//do something
}
})
i++;
if (i <toUpload.length) {
var formData = new FormData();
formData.append('files[]', toUpload[i]);
ajaxloopreq(formData);
}
}
the result of that is the progress goes only in the last uploadprogress div as a result the progress goes like crazy (parallels progress). Any idea how to fix it?

This is because your upload progress is asynchronous and you variable 'i' is incremented synchronous. So by the time your first file is uploaded the value of 'i' is already equal to the length of the total amount of files.
You can probably fix it by passing along the index with the call to ajaxloopreq:
ajaxloopreq(formata, i);
And use that to find the correct div.

Related

Heic to jpg conversion using libheif

I am trying to convert .HEIC image to .JPG using libheif.
libheif converts image on client side browser window only. So in order to save the image i converted image to base64 and then performed ajax to save the image using file_put_contents.
this.canvas.toBlob(function(blob) {
var extension = FILE_EXTENSIONS[blob.type] || ".bin";
var basename = this.filename.replace(/\.[^/.]+$/, "");
if (navigator.msSaveOrOpenBlob) {
navigator.msSaveOrOpenBlob(blob, basename + extension);
return;
}
var readers = new FileReader();
var base64image;
readers.readAsDataURL(blob);
readers.onload = function () {
var base64image = readers.result; // data <-- in this var you have the file data in Base64 format
// console.log(base64image);
// call ajax
var formData = new FormData();
formData.append('filename', basename);
formData.append('avatar', readers.result);
$.ajax('upload.php', {
method: "POST",
data: formData,
processData: false,
contentType: false,
success: function (response) {
console.log(response);
},
error: function () {
}
});
};
return;
// this.downloads.appendChild(dlink);
// dlink.click();
// URL.revokeObjectURL(url);
}.bind(this), format);
When i convert a single image then it works fine. But if i try to convert in loop it does not works.
Before completing js conversion, my php loop runs (I think this is the issue) So i tried php function sleep() and js set timeout(), But unfortunately none worked.
(function() {
var demo = new HeifDemo(libheif);
<?php $img_array = array('demo/1.heic', 'demo/2.heic', 'demo/3.heic');
foreach ($img_array as $img) : ?>
function saveImage(subject, callback) {
demo.loadUrl(subject);
callback();
}
saveImage('<?php echo $img; ?>', function() {
// demo.saveImage();
setTimeout( function(){
demo.saveImage();
}, 2500 );
});
//});
<?php sleep(4); endforeach; ?> }).call();

Change Dropzone maxFiles Dynamically

I'm trying to dynamically update the MaxFiles property each time a new image is uploaded/deleted.
By using the following code its not allowing any image to upload instead of limitize it to maxFiles. And it is not taking the value of the variable maxFile, but when i remove maxFile variable And put a number then it works fine.
got source code idea from this Answer.
!function ($) {
"use strict";
var Onyx = Onyx || {};
Onyx = {
init: function() {
var self = this,
obj;
for (obj in self) {
if ( self.hasOwnProperty(obj)) {
var _method = self[obj];
if ( _method.selector !== undefined && _method.init !== undefined ) {
if ( $(_method.selector).length > 0 ) {
_method.init();
}
}
}
}
},
userFilesDropzone: {
selector: 'form.dropzone',
init: function() {
var base = this,
container = $(base.selector);
base.initFileUploader(base, 'form.dropzone');
},
initFileUploader: function(base, target) {
var maxFile = $('.dropzone').attr('data-count');
var onyxDropzone = new Dropzone(target, {
url: ($(target).attr("action")) ? $(target).attr("action") : "data.php", // Check that our form has an action attr and if not, set one here
maxFiles: maxFile,
maxFilesize: 5,
acceptedFiles: ".JPG,.PNG,.JPEG",
// previewTemplate: previewTemplate,
// previewsContainer: "#previews",
clickable: true,
uploadMultiple: false,
});
onyxDropzone.on("success", function(file, response) {
let parsedResponse = JSON.parse(response);
file.upload_ticket = parsedResponse.file_link;
var imagecount = $('.dropzone').attr('data-count');
imagecount = imagecount - 1;
$('.dropzone').attr('data-count', imagecount);
});
},
}
}
}// JavaScript Document
function openImagePopup(id = null) {
$(".upload-images").show();
$.ajax({
url: 'fetch.php',
type: 'post',
data: {id: id},
dataType: 'json',
success:function(response) {
var imagecount = response.counts;
$('.dropzone').attr('data-count', imagecount);
}
});
}
HTML
<form action="data.php" class="dropzone files-container" data-count="">
<div class="fallback">
<input name="file" type="file" multiple />
</div>
<input type="hidden" id="imageId" name="imageId">
</form>
UPDATED ANSWER
Once instanciated, the Dropzone plugin will remains with the same options unless you change the instance inner options directly.
To change options of a Dropzone, you can do this with the following line:
$('.dropzone')[0].dropzone.options.maxFiles = newValue;
$('.dropzone')[0] returns the first dropzone DOM element
.dropzone.options return the underlying plugin instance options of the Dropzone. You can now change any options directly on this object.
In you case, you will have to change the function that initiate the popup like follow
function openImagePopup(id = null) {
$(".upload-images").show();
$.ajax({
url: 'fetch.php',
type: 'post',
data: {id: id},
dataType: 'json',
success:function(response) {
var imagecount = response.counts;
$('.dropzone')[0].dropzone.options.maxFiles = imagecount;
}
});
}
And change the dropzone onSuccess event like this:
onyxDropzone.on("success", function(file, response) {
let parsedResponse = JSON.parse(response);
file.upload_ticket = parsedResponse.file_link;
var imagecount = $('.dropzone')[0].dropzone.options.maxFiles - 1;
$('.dropzone')[0].dropzone.options.maxFiles = imagecount;
});
As you can see, You can also remove the data-count="" attribute on you element and reuse the value from the plugin instance options.maxFiles
After spending a couple of hours of trials and errors I realized using the maxFiles setting from Dropzone is not exactly what is expected in many cases. That setting will only limit uploading files through the explorer / drag&drop, but after reload more files can be uploaded. It also does not reflect any failures to the upload on the serrver side (e.g. file size too big).
Changing the value of the maxFiles setting of an already initialized Dropzone from outside ot it is impossible. For example reseting the number of allowed files after removing some images with ajax will not work.
To really control the number of files that can be uploaded to the server the counting must take place on the server. Then in the Dropzone, in the success function, we should handle the ajax response:
success: function (file, response) {
var response_data = jQuery.parseJSON(response);
if(!response_data.success) {
$(file.previewElement).addClass('dz-error');
$(file.previewElement).addClass('dz- complete');
$(file.previewElement).find('.dz-error-message').text(response_data.error);
}
}
The response is the feedback information provided by the script assigned to the action attribute of the Dropzone <form>, e.g. <form action="/uploader">.

Jquery ajax page is automatically redirecting on post request

Trying to upload multiple files through ajax but after uploading its redirecting to another blank page automatically, showing only the name of upload files
Following is the html tag
Here is the javascript function
function upload(){
var projectId = document.getElementById("projectId").children[0].value;
var referenceNo = document.getElementById("referenceNo").value;
var createdBy = document.getElementById("initiatedBy").value;
if(projectId == null)
{
alert('Please select project first');
return;
}
var formData = new FormData();
var imageFiles = document.getElementById("fileId"),
filesLength = imageFiles.files.length;
for (var i = 0; i < filesLength; i++) {
document.write(imageFiles.files[i].name);
formData.append('files',imageFiles.files[i]);
}
$("#fileId").val('');
var methodName = 'uploadBPMFiles';
formData.append('refId',referenceNo);
formData.append('projectId',projectId);
formData.append('uploadedBy',createdBy);
formData.append('processType','EOT');
$.ajax({
url: webUrl+methodName,
data: formData,
processData: false,
type: 'POST',
cache:false,
dataType: "json",
contentType: false,
enctype : "multipart/form-data",
success: function(responseData) {
alert('success');
/**console.log('responseData: '+responseData);
console.log('responseData: '+responseData);
var obj = (responseData.downloadURLs);
console.log(obj)
for (var i in obj) {
console.log(obj[i]);
//$("response")World
//$('#response').append('Link');
}
//console.log($('#response').val());
//console.log('end');
**/
}
,
error: function (responseData) {
console.log('POST failed.');
}
});
}
Note: as document.write writes to the document stream, calling document.write on a closed (loaded) document automatically calls document.open which will clear the document.
document.write(imageFiles.files[i].name); will clear your document. You have to append a new Element with the names of your files to display them on your site. To do this you can create a new Element using jQuery
$("<span>").text(imageFiles.files[i].name).appendTo("body");
Actually I was writing the uploaded file names in document. So i've removed the below line
document.write(imageFiles.files[i].name);

FormData do not send complete files in the server

so I am trying to upload multiple files to my server using jquery ajax.
So this is what i've done so far:
<input type="file" id="lab" name="lab[]" size="10" class="filestyle" multiple/>
This is my javascript that handle the change event :
function on_documents_changed(){
$("#lab").change(function() {
var formdata = new FormData();
//formdata.append('case_id', $('#case-id').text());
var inp = document.getElementById('lab').files;
for (var i = 1; i <= inp.length; i++) {
formdata.append('lab_' + i, inp.item(i));
console.log('Appended ' + i);
}
Main.Mod.do_ajax('casereport/upload_documents/laboratory', 'POST', function(){}, formdata);
});
}
This is the code for do_ajax;
function do_ajax(url,type,callback_function,formdata){
var params = {
type: type,
url: Main.Vars.host + url,
contentType: false,
cache: false,
processData:false,
dataType: 'json',
success: function(data){
callback_function(data);
}
}
if(formdata != null){
params.data = formdata;
}
$.ajax(params);
}
My problem here is, when I tried to upload, lets say, 4 files. It only read 3 files in the server. I noticed that only the last file was not read or maybe not even in $_FILES.
Your responses are greatly appreciated!
change your for loop as inp is an array you it starts from index 0 but you are accessing it by 1 so first file will be skiped:-
function on_documents_changed(){
$("#lab").change(function() {
var formdata = new FormData();
//formdata.append('case_id', $('#case-id').text());
var inp = document.getElementById('lab').files;
for (var i = 0; i < inp.length; i++) {
formdata.append('lab_' + i, inp.item(i));
console.log('Appended ' + i);
}
Main.Mod.do_ajax('casereport/upload_documents/laboratory', 'POST', function(){}, formdata);
});
}

jQuery loop array with div content inside with html2canvas

I have an array called listArray() which contains two properties pageNumber and content.
The property content holds the container div html. This is useful because I have a pagination and I don't save that info into the database in real time, instead I insert into an array and only in the end is when I insert into the database.
$container = $('#container');
$.each(listArray, function(index, value){
// So, for each index in array
// it must empty the container
// to receive a new value
$container.empty();
$container.append(value.content); // value.content = pure html
html2canvas($container, {
height: $container.height() + 180,
onrendered: function(canvas) {
var data = canvas.toDataURL('image/png');
var file = dataURLtoBlob(data);
var formObjects = new FormData();
formObjects.append('file', file);
$.ajax({
url: 'ajax_saveImage',
type: 'POST',
data: formObjects,
processData: false,
contentType: false,
});
}
});
});
As you can see my final goal is to save two or three or even more images. My problem is that all the images are being saved BUT with the last index (of the array) content.
Solved.
The solution was not loop, but instead call the function the amount of times needed. The solution came to my mind after looking at this topic Looping html2canvas
var i = 0;
function saveIt(){
$container.empty();
if(i <= listArray.length - 1){
$container.append(listArray[i]['content']);
html2canvas($container, {
height: $container.height() + 180,
letterRendering: true,
onrendered: function(canvas) {
var data = canvas.toDataURL('image/png');
var file = dataURLtoBlob(data);
var formObjects = new FormData();
formObjects.append('file', file);
$.ajax({
url: 'ajax_saveImage',
type: 'POST',
data: formObjects,
processData: false,
contentType: false,
});
i++;
saveIt(); // Important! - call the function again
}
});
}
}

Categories

Resources