I've been having a battle with dropzone.js. No matter what setting I change the plugin will only upload one or two of the files dragged into the dropzone.
Interestingly enough though if I step through all the code using debugger points I can see it going through and uploading each file. And they do upload. Every one of them.
Could this be the plugin working faster than the backend? It is getting to the success function each time so this has be utterly confused.
I have tried all the tricks.
I have the paralleUplads and maxFiles set
parallelUploads: 5,
maxFilesize: 5,
maxFiles: 5,
and I have tried setting these in the init section as well for the queue section as well
init: function() {
this.on("queuecomplete", function() {
this.options.autoProcessQueue = false;
});
this.on("processing", function() {
this.options.autoProcessQueue = true;
});
},
Without the added code above my dropzone function looks like this
$(".somediv").dropzone({
url: 'someurl',
async: false,
clickable: false,
sending: function(file, xhr, formData) {
var fileType = file.type;
var form_data = new FormData(file);
fileType = fileType.substring(fileType.indexOf("/") + 1);
formData.append("data", file);
formData.append("documentID", 0);
formData.append("dataTypeCode", fileType);
formData.append("dataDescription", file.name);
formData.append('filepart', form_data)
},
addedfile: function(file) {
var _this = this,
reader = new FileReader();
reader.onload = function(event) {
_this.processQueue()
};
reader.readAsDataURL(file);
},
success: function(data) {
var fileType = data.type;
fileType = fileType.substring(fileType.indexOf("/") + 1);
iconImg(fileType)
console.log('uploaded ' + data)
var statusCode = 'AD'
var text = "'Attachment Added' by " + currentUser.employeeId
statusCodeChange(statusCode, brCode, incidentId, text)
var randomNum = Math.random() * 20
table.row.add({
"dataDescription": data.name,
"dataTypeCode": fileType,
"documentTimeStamp": formatDate(new Date()),
"documentID": randomNum
}).draw(false)
.node();
growl("Attachment Uploaded!", {});
}
});
Related
I'm having a difficult time trying to get the below code to work in IE. The code works as expected in Firefox, Chrome, and Edge; but not in IE. I would ignore it not working in IE, but it's the default browser used at work.
The code is written to upload multiple files into a specific SharePoint document library. I got the code from this post https://social.msdn.microsoft.com/Forums/office/en-US/bb590f35-da1b-4905-baa0-fb85a275abf6/multiple-files-upload-in-document-library-using-javascript-object-model?forum=appsforsharepoint. It's the last post, and it does work great in the mentioned browsers. Any suggestions on how to get it to work in IE will greatly be appreciated. Thank you in advance.
Script is below:
jQuery(document).ready(function() {
fileInput = $("#getFile");
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', registerClick);
});
function registerClick() {
//Register File Upload Click Event
jQuery("#addFileButton").on('click', readFile);
}
var arrayBuffer;
function readFile() {
//Get File Input Control and read th file name
var element = document.getElementById("getFile");
var fileCount = element.files.length;
var filesUploaded = 0;
for (var i = 0; i < fileCount; i++) {
let file = element.files[i];
var reader = new FileReader();
reader._NAME = element.files[i].name
reader.onload = function(e) {
let fileactualName = e.target._NAME;
uploadFile(e.target.result, fileactualName);
}
reader.onerror = function(e) {
alert(e.target.error);
}
reader.readAsArrayBuffer(file);
}
}
function uploadFile(arrayBuffer, fileName) {
//Get Client Context,Web and List object.
var clientContext = new SP.ClientContext();
var oWeb = clientContext.get_web();
var oList = oWeb.get_lists().getByTitle('Comms Shared Files');
//Convert the file contents into base64 data
var bytes = new Uint8Array(arrayBuffer);
var i, length, out = '';
for (i = 0, length = bytes.length; i < length; i += 1) {
out += String.fromCharCode(bytes[i]);
}
var base64 = btoa(out);
//Create FileCreationInformation object using the read file data
var createInfo = new SP.FileCreationInformation();
createInfo.set_content(base64);
createInfo.set_url(fileName);
//Add the file to the library
var uploadedDocument = oList.get_rootFolder().get_files().add(createInfo)
//Load client context and execcute the batch
clientContext.load(uploadedDocument);
clientContext.executeQueryAsync(QuerySuccess, QueryFailure);
}
function QuerySuccess() {
alert('File Uploaded Successfully.');
}
function QueryFailure(sender, args) {
console.log('Request failed with error message - ' + args.get_message());
}
In SharePoint 2010, we can use SharePoint designer to open the v4.master(defualt), and add "IE=11" in "X-UA-Compatible".
<meta http-equiv="X-UA-Compatible" content="IE=8,IE=11"/>
In SharePoint 2013/2016/2019/online, we can use REST API to upload the files to document library with jQuery code.
<input id="inputFile" type="file" multiple="multiple"/>
<input id="uploadDocumentButton" type="Button" value="Upload Document">
<script src="https://code.jquery.com/jquery-1.12.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
var libraryTitle="DL";
$(function(){
$("#uploadDocumentButton").click(function () {
if (document.getElementById("inputFile").files.length === 0) {
alert("Select a file!");
return;
}
for(var i = 0; i < document.getElementById("inputFile").files.length; i++){
var file = document.getElementById("inputFile").files[i];
uploadFileSync(libraryTitle, file.name, file);
}
alert("upload complete.");
});
});
function uploadFileSync(folderUrl, filename, file){
var reader = new FileReader();
reader.onloadend = function(evt){
if (evt.target.readyState == FileReader.DONE){
var buffer = evt.target.result;
var completeUrl =_spPageContextInfo.webAbsoluteUrl
+ "/_api/web/GetFolderByServerRelativeUrl('"+folderUrl+"')/Files/add(url='" + filename + "',overwrite=true)";
$.ajax({
url: completeUrl,
type: "POST",
data: buffer,
async: false,
processData: false,
headers: {
"accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"content-length": buffer.byteLength
},
complete: function (data) {
//alert("upload complete.");
//console.log(data.responseJSON.d.ServerRelativeUrl);
},
error: function (err) {
alert('failed');
}
});
}
};
reader.readAsArrayBuffer(file);
}
</script>
I have a multi-file input field:
<input type="file" class="image_file" multiple>
I am using FileReader to show previews of images whilst they are being uploaded.
I now also want to show a progress bar on each individual image whilst it is being uploaded. Here is what I have tried:
$('.image_file').change(function() {
var input = $(this);
var files = this.files;
var total = files.length;
var url = input.attr('data-url');
for (var i = 0; i < total; i++) {
var formData = new FormData();
var file = files[i];
formData.append('image_file', file);
var reader = new FileReader();
reader.onload = function(e) {
var container = $('.photos .photo:not(.active):first');
if (container.length) {
container.css('background-image', 'url(' + e.target.result + ')').addClass('active uploading');
}
};
reader.readAsDataURL(file);
$.ajax({
type: 'post',
url: url,
data: formData,
cache: false,
processData: false,
contentType: false,
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
var progressElem = container.find('progress');
if (myXhr.upload) {
myXhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
progressElem.attr({
value: e.loaded,
max: e.total
});
}
}, false);
}
return myXhr;
},
success: function(result) {
if (result.status == true) {
$('.success-message').show();
}
else {
alert('There was an error uploading your file.);
}
}
});
}
});
The issue I am having is on this line in the xhr function:
var progressElem = container.find('progress');
The image preview appears but the AJAX upload isn't working. No errors are shown in the console either. I think because var container was set within the reader.onload function, the xhr function doesn't have access to it.
If I move that var outside of the function, the image upload works but only one image preview and one progress bar is shown.
Does anybody know the correct way to do this?
The problem is that there is a single xhr that is created and deleted when the for loop runs. The previous xhr are destroyed once the code finishes so it will never run.
The way I got round this was to not use jQuery and/or create a new xmlhttprequest for each for loop.
var array = []; //ADDED HERE
$('.image_file').change(function() {
var input = $(this);
var files = this.files;
var total = files.length;
var url = input.attr('data-url');
for (var i = 0; i < total; i++) {
var formData = new FormData();
var file = files[i];
formData.append('image_file', file);
var reader = new FileReader();
reader.onload = function(e) {
var container = $('.photos .photo:not(.active):first');
if (container.length) {
container.css('background-image', 'url(' + e.target.result + ')').addClass('active uploading');
}
};
reader.readAsDataURL(file);
array[array.Length] = $.ajax({ //ADDED HERE
type: 'post',
url: url,
data: formData,
cache: false,
processData: false,
contentType: false,
xhr: function() {
var myXhr = $.ajaxSettings.xhr();
var progressElem = container.find('progress');
if (myXhr.upload) {
myXhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
progressElem.attr({
value: e.loaded,
max: e.total
});
}
}, false);
}
return myXhr;
},
success: function(result) {
if (result.status == true) {
$('.success-message').show();
} else {
alert('There was an error uploading your file.);
}
}
});
}
});
I need to emphasis that I haven't looked through your code completely but hopefully this will steer you in the right direction.
Looking at your question description, I assume:
Image Preview works since you mentioned "The image preview appears"
Image uploads since you mentioned "If I move that var outside of the function, the image upload works..."
Where is the problem then?
The problem is your variable container is not accessible inside xhr() function as you mentioned already.
What is the solution?
There can be many possible solutions for you problem, but I think moving the ajax request block inside reader.onload is better idea since, the variable container will be accessible to child function and it will be called only if vaild file is being uploaded.
$('.image_file').change(function() {
var input = $(this);
var files = this.files;
var total = files.length;
var url = input.attr('data-url');
for (var i = 0; i < total; i++) {
var formData = new FormData();
var file = files[i];
formData.append('image_file', file);
var reader = new FileReader();
reader.onload = function(e) {
var container = $('.photos .photo:not(.active):first');
if (container.length) {
var ajaxFunction = function() {
var myXhr = $.ajaxSettings.xhr();
var progressElem = this.find('progress');
if (myXhr.upload) {
myXhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
progressElem.attr({
value: e.loaded,
max: e.total
});
}
}, false);
}
return myXhr;
};
container.css('background-image', 'url(' + e.target.result + ')').addClass('active uploading');
$.ajax({
type: 'post',
url: url,
data: formData,
cache: false,
processData: false,
contentType: false,
xhr: ajaxFunction.bind(container),
success: function(result) {
if (result.status == true) {
$('.success-message').show();
} else {
alert('There was an error uploading your file.');
}
}
});
}
};
reader.readAsDataURL(file);
}
});
.photo {
display: none;
height: 200px;
width: 200px;
float: left;
}
.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" class="image_file" multiple data-url="http://httpbin.org/post">
<div class="photos">
<div class="photo">
<progress></progress>
</div>
<div class="photo">
<progress></progress>
</div>
</div>
Updated: used bind() function to pass current value of the variable container to the ajaxFunction()
I have had this issue start to appear with the device file name being created in this format:
.../DCIM/Camera/IMG_20170819_155509.jpg
But the media file data when using Cordova captureImage being returned as:
.../DCIM/Camera/1503140105277.jpg
Therefore being unable to return the image.
Here is the code:
$('body').off('click', '#add-image-inspect-attr-list').on('click', '#add-image-inspect-attr-list', function(event) {
var options = { limit: 1 };
navigator.device.capture.captureImage(inspectAttrPictureSuccess, inspectPictureError, options);
$(this).off();
});
function inspectAttrPictureSuccess(imageData) {
console.log(imageData);
var countOfImg = $('.image-display-inspect-attr-list').children().length;
var file = {
ContentType: "image/jpeg",
base64: imageData,
Data: imageData,
ID: countOfImg
};
var fileName = file.base64;
inspectShowAttrFile(fileName,0);
}
function inspectShowAttrFile(fileName, type) {
var countOfImg = $('.image-display-inspect-list').children().length;
$('.image-display-inspect-list').append('<img id="inspect-img-index-' + countOfImg + '" class="img-responsive img-thumbnail img-inspect" src="' + fileName[0].fullPath + '">');
}
The app is built with cordova 6.3.1 and the device has andriod 4.4.2
This works on some devices but not others
To get around this issue, I had to check what the last file added was to the image file location. Get the folder path, get the latest file added, then update the image data created by the captureImage function with the new file name and location data:
function inspectAttrPictureSuccess(imageData) {
var deviceImageFolder = imageData[0].localURL.replace(imageData[0].name, '');
window.resolveLocalFileSystemURL(deviceImageFolder, function (dirEntry) {
var directoryReader = dirEntry.createReader();
directoryReader.readEntries(successfile, failfile);
}, function (err) {
var errToSave = err.message;
});
function successfile(entries) {
var latestimage = entries[entries.length - 1];
imageData[0].fullPath = latestimage.fullPath
imageData[0].localURL = latestimage.nativeURL
imageData[0].name = latestimage.name
var countOfImg = $('.image-display-inspect-attr-list').children().length;
var file = {
Filename: "inspect-attr-img-" + Math.random().toString(36).substring(2, 15) + ".jpg",
ContentType: "image/jpeg",
base64: imageData,
Data: imageData,
ID: countOfImg
};
inspectImageAttrFileSendAry.push(file);
inspectImageFileSendALLAry.push(file);
console.log(inspectImageAttrFileSendAry);
console.log(inspectImageFileSendALLAry);
var fileName = file.base64;
inspectShowAttrFile(fileName, 0);
}
function failfile(error) {
console.log("Failed to list directory contents: ", error);
}
}
I am new to JS, for last few days I am stuck at compressing image at client side. What I want to do is, User drops bunch of images (can be more than 10) at dropzone they should be compressed using JIC and once user clicks a button to upload all the compressed files get uploaded to the server.
So far my code is able to compress and upload only if one image is dropped, but when I drop multiple images all images remain uncompressed but one. I am not sure what wrong I am doing. I have tried to follow the solutions from this post but couldn't achieve my goal. Code I am using is as follows:
Dropzone.autoDiscover=false;
var myDropZone=new Dropzone("#dropzonePreview",{
url:"/dragdrop",
autoProcessQueue:false,
acceptedFiles: 'image/*',
parallelUploads: 10,
init:function(){
this.on('addedfile', function(file){
_this = this;
////console.log("Added File");
$('#userphoto').css('color', "transparent");
EXIF.getData(file, function(){ // async call
var lat=EXIF.getTag(this,"GPSLatitude");
var lon=EXIF.getTag(this,"GPSLongitude");
geocoder.geocode( { 'latLng': temp }, function(results, status) { // another async call });
}
});
myReader2 = new FileReader(); // Reading image for compression purpose
myReader2.onload = function(event) {
console.log(file.status);
// var i = new Image();
var i = document.getElementById("source_image");
i.src = event.target.result;
i.onload = function() {
var source_image = document.getElementById('source_image');
var quality = 70;
comp = jic.compress(source_image, 70, "jpg"); // Link to function can be found at the end of code.
var editedFile = base64ToFile(comp.src, file); // same function used in mentioned stackoverflow post.
// Replace original with resized
var origFileIndex = myDropZone.files.indexOf(file);
myDropZone.files[origFileIndex] = editedFile;
editedFile.status = Dropzone.ADDED;
myDropZone.enqueueFile(editedFile);
delete source_image;
};
};
myReader2.readAsDataURL(file);
});
this.on("sending",function(file,xhr,formData){
//appending some data to formData
});
this.on("complete", function(file){
// processing like removing objects of file from drop zone
});
}
});
$('#upload').click(function(evt){ // Button that triggers uploading file
myDropZone.processQueue();
}
Link to function. Your help would be really appreciated. Thank you.
I have found this issue solution. it's work for me.
Please check
function base64ToFile(dataURI, origFile) {
var byteString, mimestring;
if(dataURI.split(',')[0].indexOf('base64') !== -1 ) {
byteString = atob(dataURI.split(',')[1]);
} else {
byteString = decodeURI(dataURI.split(',')[1]);
}
mimestring = dataURI.split(',')[0].split(':')[1].split(';')[0];
var content = new Array();
for (var i = 0; i < byteString.length; i++) {
content[i] = byteString.charCodeAt(i);
}
var newFile = new File(
[new Uint8Array(content)], origFile.name, {type: mimestring}
);
// Copy props set by the dropzone in the original file
var origProps = [
"upload", "status", "previewElement", "previewTemplate", "accepted"
];
$.each(origProps, function(i, p) {
newFile[p] = origFile[p];
});
return newFile;
}
Dropzone.autoDiscover = false;
jQuery(document).ready(function($) {
var myDropZone=new Dropzone("#dropzonePreview",{
url:"/dragdrop",
autoProcessQueue:false,
acceptedFiles: 'image/*',
parallelUploads: 10,
init:function(){
this.on("sending",function(file,xhr,formData){
});
this.on("complete", function(file){
});
}
});
myDropZone.on("addedfile", function(file) {
var reader = new FileReader();
reader.addEventListener("load", function(event) {
var origImg = new Image();
origImg.src = event.target.result;
origImg.addEventListener("load", function(event) {
comp = jic.compress(origImg, 30, "jpg");
var resizedFile = base64ToFile(comp.src, file);
var origFileIndex = myDropZone.files.indexOf(file);
myDropZone.files[origFileIndex] = resizedFile;
myDropZone.enqueueFile(resizedFile);
});
});
reader.readAsDataURL(file);
});
$('#upload').click(function(e){ // Button that triggers uploading file
e.preventDefault();
myDropZone.processQueue();
});
});
I'm trying to use the angular upload library to upload a file and see the percentage of uploading. The method itself works well and the file can be uploaded on my server but when i try to see the percentage it shows me this
progress: 6%
progress: 100%
or anyway it shows only the first percentage, in this case 6% but could be 40% or something else, and then directly 100%. This is the code
$scope.uploadFileFunction = function(file) {
var uploadUrl = "url";
var newJson;
var json = [];
json.push(newJson);
var self = this;
self.loading = true;
var fd = new FormData();
if (file != undefined && file != null) {
fd.append('file', file);
}
fd.append('json', angular.toJson(json));
Upload.http({
url: uploadUrl,
transformRequest: angular.identity,
method: 'POST',
headers: {
'Content-Type': undefined
},
data: fd
}).then(function (data, status) {
self.loading = false;
$scope.uploadError = false;
}, function (resp) {
self.loading = false;
$scope.uploadError = true;
}, function (evt) {
$scope.upPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('progress: ' + $scope.upPercentage + '% ');
});
};
is it normal? It happens also if i upload large files. This is the link to the library i'm using https://github.com/danialfarid/ng-file-upload