File Upload Using jQuery not working in IE - javascript

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>

Related

FileReader with multi Ajax file upload and progress

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()

How to pass different types of data on ajax send() function to PHP?

I am trying to send a file(pdf file) as well as user text input using ajax using vanilla javascript please dont post any jquery answers.
formData contains the pdf file and formVal contains the user text input.
If I remove formVal from the request.send function then the file is uploaded but if I include formVal the send function does not work as nothing gets uploaded.
var formData = new FormData();
var dropzone = document.getElementById('dropzone');
var sub = document.getElementById('subForm');
var uploadFile = function (formVal) {
var request = new XMLHttpRequest();
request.onload = function(){
var data = this.responseText;
console.log(data);
//window.location.reload();
}
request.open('post', 'index.php');
request.send(formData, formVal);
}
dropzone.ondrop = function (event) {
event.preventDefault();
document.getElementById('para1').innerHTML = "File uploaded";
var files = event.dataTransfer.files;
//uploadFile(event.dataTransfer.files,);
var i;
for(i = 0; i<files.length; i = i+1){
formData.append('file[]', files[i]);
}
return false;
}
sub.onclick = function () {
var code = document.getElementById('cCode').value;
var size = document.getElementById('cSize').value;
var dd = document.getElementById('cDD').value;
var val = "c=" +code+"&s="+size+"&d="+dd;
if(formData.get('file[]') === null){
alert("Drang and drop PDF file");
}else{
uploadFile(val);
}
}

Multiple Base64 image within 1 array causes overriding

Let's say I want to upload 2 images to an ajax, I will send them using this format
{ "base64StringName:" : "[ {"1": "base64_1"}, {"2" : "base64_2"} ]"}
So its an object that contains an array of objects of base64 strings
To do so, I will need to create an array and inside this array, I will push json objects into it.
Here is my code for this:
<script>
var test ='';
var imageArray =[];
var imageObject ={};
$('#inputFileToLoad').on('change', function(){
imageArray.length = 0;
fileCount = this.files.length;
for(i = 0; i < fileCount; i++){
var file = document.querySelector('#inputFileToLoad').files[i];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
test = reader.result.split(',')[1];
console.log(test);
imageObject[i] = test;
imageArray.push(imageObject);
};
reader.onerror = function (error) {
alert('Error: ', error);
};
}
});
$('#inputFileToLoadButton').on('click', function(){
console.log(imageArray);
$.ajax({
url:"some url",
method:"POST",
data: {
"base64String": imageArray
}
,success: function () {
swal("Success!","Upload Finished!","success");
//add redirect!
},
error: function (jqXHR) {
swal("Error",jqXHR.responseText, "error");
}
});
});
</script>
However, I encounter a problem, my first object inside the array somehow gets overwritten.
it becomes
{ "base64StringName:" : "[ {"1": "base64_2"}, {"2" : "base64_2"} ]"}
Also when i printed out the first base64 encoded file at console.log(test); it is undefined, but when i printed out the second base64 encoded file, it prints the second file only.
try this:
var test = '';
var imageArray = [];
var imageObject;
$('#inputFileToLoad').on('change', function() {
imageArray.length = 0;
fileCount = this.files.length;
for (i = 0; i < fileCount; i++) {
debugger;
var file = document.querySelector('#inputFileToLoad').files[i];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function() {
test = this.result.split(',')[1];
imageObject = {};
imageObject[index] = test;
imageArray.push(imageObject);
}.bind({
index: i
});
reader.onerror = function(error) {
alert('Error: ', error);
};
}
});

Compress image by tweaking dropzone.js

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();
});
});

How can i change javascript script into a jquery functional code

Hey guys am new to jQuery,How can I change this javascript code into jQuery functional code so that I call it whenever I want at any object
LIKE: $("#profile_img").uploader();
Apparently this code works fine, but the problem I have is I have to populate the code every time I need to upload a file in a different file input upload.
var input = document.getElementById("choosen_feeds_image"),
formdata = false;
if (window.FormData) {
formdata = new FormData();
document.getElementById("feeds_upload_btn").style.display = "none";
}
if (input.addEventListener) {
input.addEventListener("change", function (evt) {
var i = 0, len = this.files.length, img, reader, file;
document.getElementById("response").innerHTML = ""
for (; i < len; i++) {
file = this.files[i];
if (!!file.type.match(/image.*/)) {
if (window.FileReader) {
reader = new FileReader();
reader.onloadend = function (e) {
showUploadedItem(e.target.result);
};
reader.readAsDataURL(file);
}
if (formdata) {
formdata.append("feeds_image", file);
}
if (formdata) {
$.ajax({
url: "member/feeds_image_upload",
type: "POST",
data: formdata,
processData: false,
contentType: false,
success: function (res) {
if (res.length <= 40) {
document.getElementById('feeds_image_response').innerHTML = res;
$("#feeds_image_response").css('display', 'none');
} else {
document.getElementById("response").innerHTML = res;
$("#response").css('display', 'none');
}
}
});
}
} else {
document.getElementById("response").innerHTML = "";
alert("Sorry, You choose unsupported file");
}
}
}), false
};
you can type all inside a function like this
function uploader(){
console.log('myFuntionUploader');
}
and then call the function like this
uploader();

Categories

Resources