Ajax Uploader High Memory Consumption with Large Files - javascript

I am trying to use the FileReader API to upload files to a server.
File uploading works well. Although I am uploading the file in chunks, but the memory used by the FormData object is not freed after the upload, that is uploading a large file crashes the browser.
Here's my code:
I was wondering what it is that I am doing wrong?
function uid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
function parseFile(file) {
var fileSize = file.size;
var chunkSize = 10 * 1024 * 1024; // bytes
var offset = 0;
var block = null;
var doUpload = null;
var sendEndSignal = null;
var id = uid();
var chunks = {};
var r = new FileReader();
var xhr = new XMLHttpRequest();
var fd = new FormData();
var foo = function (evt) {
}
block = function (_offset, length, _file) {
var blob = _file.slice(_offset, length + _offset);
r.onload = foo;
r.onloadend = (
function (file, id, off) {
return function (evt) {
if (evt.target.error == null) {
off += chunkSize;
if (off >= fileSize) {
console.log("Done reading file");
return;
}
var fnc = block;
doUpload(file, evt.target.result, id, Math.floor(off / chunkSize), chunks, chunkSize, block, off);
} else {
alert("Read error: " + evt.target.error);
return;
}
}
})(_file, id, _offset);
r.readAsDataURL(blob);
}
doUpload = function (file, data, id, chunk, chunks, chunkSize,nx,off) {
xhr = new XMLHttpRequest();
fd = new FormData();
fd.append(file.name + "-----" + id + "-----" + String(chunk), data);
xhr.open("post", "Handler1.ashx", true);
xhr.send(fd);
xhr.addEventListener('readystatechange',
function (e) {
if (this.readyState === 4) {
chunks[Math.floor(chunk)] = 1;
var cnt = 0;
var cntDone = 0;
for (var key in chunks) {
if (chunks.hasOwnProperty(key)) {
cnt++;
if (chunks[key] === 1)
cntDone += 1;
}
}
if (nx)
nx(off,chunkSize,file);
if (cnt === Math.ceil(file.size / chunkSize) && cnt === cntDone)
sendEndSignal(file, id, cnt - 1);
}
});
}
sendEndSignal = function (file, id, num) {
fd = new FormData();
xhr = new XMLHttpRequest();
fd.append("Done-----" + file.name + "-----" + id, num);
xhr.open("post", "Handler1.ashx", true);
xhr.send(fd);
}
block(offset, chunkSize, file);
}
Thank you.
Update:
I solved my problem using jquery post instead of XMLHttpRequest and FormData.
Here's What I have done:
<script type="text/javascript">
function uid() {
function s4() {
return Math.floor((1 + Math.random()) * 0x10000)
.toString(16)
.substring(1);
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
function parseFile(file,index) {
var fileSize = file.size;
var chunkSize = 10 * 1024 * 1024; // bytes
var offset = 0;
var block = null;
var doUpload = null;
var sendEndSignal = null;
var id = uid();
var chunks = {};
var r = new FileReader();
var foo = function (evt) {
}
block = function (_offset, length, _file) {
var blob = _file.slice(_offset, length + _offset);
var div = document.getElementById("file-" + String(index));
div.innerHTML = div.innerHTML + "*";
r.onload = foo;
r.onloadend = (
function (file, id, off) {
return function (evt) {
if (evt.target.error == null) {
doUpload(file, evt.target.result, id, Math.floor(off / chunkSize), chunks, chunkSize, block, off,index);
} else {
alert("Read error: " + evt.target.error);
return;
}
}
})(_file, id, _offset);
r.readAsDataURL(blob);
}
doUpload = function (file, data, id, chunk, chunks, chunkSize, nx, off,ind) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "WebForm1.aspx/ProcessData",
data: "{'data':'" + data + "','name':'" + file.name + "-----" + id + "-----" + String(chunk) + "'}",
success: function (dd) {
debugger;
chunks[Math.floor(chunk)] = 1;
var cnt = 0;
var cntDone = 0;
for (var key in chunks) {
if (chunks.hasOwnProperty(key)) {
cnt++;
if (chunks[key] === 1)
cntDone += 1;
}
}
if (cnt === Math.ceil(file.size / chunkSize) && cnt === cntDone)
sendEndSignal(file, id, cnt - 1,ind);
if (nx) {
debugger;
off += chunkSize;
if (off >= file.size) {
return;
}
nx(off, chunkSize, file);
}
},
error: function (result) {
alert(JSON.stringify(result));
}
});
}
sendEndSignal = function (file, id, num,ind) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "WebForm1.aspx/ProcessData",
data: "{'data':'" + num + "','name':'" + "Done-----" + file.name + "-----" + id + "'}",
success: function (dd) {
var div = document.getElementById("file-" + String(ind));
div.innerHTML = "<b>" + file.name + "</b> => DONE!!!!";
},
error: function (result) {
alert(JSON.stringify(result));
}
});
}
block(offset, chunkSize, file);
}
function xx(inp) {
var i = 0;
var file;
var node = document.getElementById("dupl");
debugger;
while (node.hasChildNodes())
node.removeChild(node.lastChild);
for (i = 0; i < inp.files.length; i++) {
file = inp.files[i];
var dd = document.createElement("div");
dd.id = "file-" + String(i);
dd.innerHTML = "<b>" + file.name + "</b>";
document.getElementById("dupl").appendChild(dd);
}
for (i = 0; i < inp.files.length; i++) {
file = inp.files[i];
parseFile(file,i);
}
}
</script>
Hope It will be useful for someone.

Related

upload progress bar is jumpy

I've been working on an upload progress bar. The problem is, I can't seem to clean up the motion. It's jumpy, and I think it comes down to not understanding the finer details up the the upload process. What can I do to make this motion smoother?
This script has two movements, progressBarDisp is the target for the upload itself. Then it has a second bar for ajax upon files being processed and receiving a confirmation from the server.
My jumpy item is the progressBarDisp - I can't figure out why it's so jumpy.
$('input[type=file].dicomUpload').on("change", function() {
var files = $(this)[0].files;
//console.log(files);
var theCase = $(this).parent().find('input[name="theCase"]');
var casenum = $(this).parent().find('input[name="casenum"]');
var phase = $(this).parent().find('input[name="phase"]');
var vidnum = $(this).parent().find('input[name="vidNum"]');
processUpload(theCase, casenum, phase, files, vidnum);
});
function processUpload(theCase, casenum, phase, myfiles, vidnum) {
//console.log("Processing: "+vidnum.val());
var progressBox = $('#uploadDicomBox' + casenum.val() + '-' + vidnum.val()).find(".uploadprogress");
progressBox.slideDown();
var progressBarDisp = progressBox.find(".progressBarDisp");
var progressBarComp = progressBox.find(".progressBarComp");
var progressBarText = progressBox.find(".progressText");
progressBarText.text('Processing Upload.');
//run this in two parts - get the file sizes of the acceptable file types
var nBytes = 0;
var uploadedBytes = 0;
var completeBytes = 0;
var tempList = new Array();
$.each(myfiles, function(i, file) {
//console.log(file.name+" -- "+file.name.indexOf("."));
// do any file checking logic here
tempList.push(file);
});
myfiles = tempList;
$.each(myfiles, function(i, file) {
nBytes += file.size;
});
console.log("beginning uploads: " + theCase.val() + ", " + casenum.val() + ", " + phase.val() + ", " + nBytes + ", " + vidnum.val());
//console.log(myfiles);
if (myfiles.length < 1) {
progressBarText.text('No valid file types selected.');
}
//tracking variable
var maxup = 0;
$.each(myfiles, function(i, file) {
//file sizes are going to be an issue for me, these need to be individual file uploads
progressBarText.text('Upload Progress');
// Create a FormData object
var formData = new FormData();
formData.append('casenum', casenum.val());
formData.append('phase', phase.val());
formData.append('theCase', theCase.val());
formData.append('vidnum', vidnum.val());
formData.append('file', file);
$.ajax({
xhr: function() {
var xhr = new window.XMLHttpRequest();
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
maxup = Math.max(maxup, evt.loaded);
var percentComplete = (maxup / evt.total) * 100;
//Do something with upload progress here
//console.log("Upload Status: "+evt.loaded+" / "+evt.total+" -- "+((evt.loaded/evt.total)*100)+"%");
progressBarDisp.width(percentComplete + '%');
progressBarText.text('Upload Progress: Uploading ' + myfiles.length + ' files');
if (percentComplete == 100) {
progressBarText.text('Upload Progress: Upload Complete. Now Processing.');
}
}
}, false);
return xhr;
},
type: 'POST',
url: BASE_URL,
cache: false,
contentType: false,
processData: false,
data: formData,
beforeSend: function(xhr) {
uploadedBytes += file.size;
//progressBarDisp.width(((uploadedBytes/nBytes)*100)+'%');
progressBarText.text('Upload Progress: Uploading ' + myfiles.length + ' files');
},
success: function(result) {
console.log(result);
var resJSON = JSON.parse(result);
if (resJSON.status == "success") {
completeBytes += file.size;
processed = Math.round((completeBytes / nBytes) * myfiles.length);
progressBarComp.width(Math.round((processed / myfiles.length) * 100) + '%');
progressBarText.text('Upload Progress: Processed ' + (processed) + ' of ' + myfiles.length + ' files');
/*if(myfiles.length == (i+1)){
progressBarText.text('Upload Progress: Complete');
}
else{
progressBarText.text('Upload Progress: Uploaded '+(i+1)+' of '+myfiles.length+' files');
}
*/
}
},
error: function(err) {
//console.log(err);
uploadedBytes += file.size;
progressBarDisp.width(((uploadedBytes / nBytes) * 100) + '%');
}
});
});
}

How can I determine why the following JavaScript code inserts the timer record twice?

The following JavaScript code inserts the timer record twice, it's exact duplicate, why is this, and how can I fix it?
We think it's happening at the onbeforeunload but I know nothing about JavaScript.
if (typeof(HandleTimerII) === undefined) {
HandleTimer = {};
}
var execCounter;
execCounter = 0;
var HandleTimerII = {
sessionStartPoint: null,
sessionStartTime: null,
sessionSavedChange: false,
sessionUser: null,
sessionCase: null,
sessionId: null,
savecCount: null,
entityName: null,
sessionStart: function(formContext) {
//debugger;
this.entityName = Xrm.Page.data.entity.getEntityName();
this.sessionStartPoint = Date.now();
this.sessionStartTime = new Date().toISOString();
this.sessionCase = {
Id: Xrm.Page.data.entity.getId(),
LogicalName: this.entityName
};
this.sessionUser = {
Id: Xrm.Page.context.getUserId(),
LogicalName: "systemuser"
};
this.sessionId = this.generateSessionId();
window.onbeforeunload = function() {
if (execCounter === 0) {
if (HandleTimerII.entityName === "cog_case") HandleTimerII.logSessionToCRM();
}
execCounter += 1;
};
},
generateSessionId: function() {
var S4 = function() {
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
};
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
},
sessionSave: function(formContext) {
this.sessionSavedChange = true;
},
logSessionToCRM: function() {
debugger;
//context = HandleTimerII._context;
var sessionDuration = Math.round((Date.now() - HandleTimerII.sessionStartPoint) / 1000);
var caseAssigneeRec = {};
caseAssigneeRec.cog_AssigneeId = HandleTimerII.sessionUser;
caseAssigneeRec.cog_caseworktime = sessionDuration;
caseAssigneeRec.cog_Case = HandleTimerII.sessionCase;
caseAssigneeRec.cog_SavedChanges = HandleTimerII.sessionSavedChange;
caseAssigneeRec.cog_AssignmentReason = HandleTimerII.sessionId;
caseAssigneeRec.cog_SessionStart = HandleTimerII.sessionStartTime;
caseAssigneeRec.cog_SessionEnd = new Date().toISOString();
XrmServiceToolkit.Rest.Create(
caseAssigneeRec,
"cog_caseassigneesSet",
function(result) {
caseAsigneeId = result.cog_caseassigneesid;
console.log("saved assignee record");
},
function(error) {
equal(true, false, error.message);
},
true
);
}
};

FormData content length Limitation in Jquery, Ajax When sending Large Image Files In Using Array with FormData

I have 3 Image or Multiple Images Array whose total size is approx. 29mb or above. I am try to post it on server Side using Ajax with Form data. But It shows error when i try to post large data using FormData in MVC is there any solution. when i try to post data it shows error on client side means go into the request.fail section
This is My Jquery Code
var filess = new Array();
var num = 4;
var IsAlready = false;
$(document).ready(function() {
document.getElementById('pro-image').addEventListener('change', readImage, false);
$( ".preview-images-zone" ).sortable();
$(document).on('click', '.image-cancel', function() {
debugger;
let no = $(this).data('no');
let Id = this.id;
$(".preview-image.preview-show-"+no).remove();
for (var i = 0; i < filess.length; i++) {
debugger;
filess = $.grep(filess, function(value) {
return value.name != Id;
});
}
});
});
function readImage() {
if (window.File && window.FileList && window.FileReader) {
var files = event.target.files;
var output = $(".preview-images-zone");
for (var i = 0; i < files.length; i++) {
$.grep(filess, function (n) {
if (n.name == files[i].name) {
IsAlready = true;
}
})
if (IsAlready)
{
alert("Same Name File Exist");
$("#pro-image").val('');
IsAlready = false;
return false;
}
}
var anyWindow = window.URL || window.webkitURL;
for (var i = 0; i < files.length; i++) {
filess.push(files[i]);
var file = null;
file = files[i];
if (!file.type.match('image')) continue;
var objectUrl = anyWindow.createObjectURL(files[i]);
var html = '<div class="preview-image preview-show-' + num + '" >' +
'<div class="image-cancel" data-no="' + num + '" id="' + files[i].name + '">x</div>' +
'<div class="image-zone"><img id="pro-img-' + num + '" src="' + objectUrl + '"></div>' +
'</div>';
output.append(html);
num = num + 1;
window.URL.revokeObjectURL(files[i]);
}
$("#pro-image").val('');
}
else {
console.log('Browser not support');
}
}
$("#submit").click(function () {
event.preventDefault();
debugger;
var url = "/Administration/CreateAlbum";
var albumName = $("#AlbumName").val();
var albumDescription = $("#AlbumDescription").val();
var IsActive = $("#IsActive").val();
var filess = new Array();
var data = new FormData();
data.append('albumName', albumName);
data.append('albumDescription', albumDescription);
data.append('IsActive', IsActive);
$("#submit").prop("disabled", true);
for (var i = 0; i < filess.length; i++) {
data.append('image', filess[i] );
}
var request = $.ajax({
url: url,
enctype: 'multipart/form-data',
type: 'POST',
processData: false,
contentType: false,
cache: false,
timeout: 600000,
data: data
});
request.done(function (response) {
$("#resultCode").html(response.ResultCode);
$("#resultMessage").html(response.ResultMessage);
$('#reasonCode').val("");
$('#quantity').val("");
$('#inventoryCode').val("");
$('#unitCost').val("");
});
request.fail(function (jqXHR, textStatus) {
alert("Request failed: " + textStatus);
});
});
As discussed, you need to set the maxAllowedContentLength in the web.config
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="YOUR SIZE" />
</requestFiltering>
</security>
</system.webServer>
thanks
For large file upload.
ini_set('upload_max_filesize', '10M'); ini_set('post_max_size', '10M');
your files array is blank and no need to specify enctype. Here in Ajax
var files = array();
if you have multiple files,then append like
data.append('image[]', filess[i] );
var filess = new Array();
var num = 4;
var IsAlready = false;
$(document).ready(function() {
document.getElementById('pro-image').addEventListener('change', readImage, false);
$( ".preview-images-zone" ).sortable();
$(document).on('click', '.image-cancel', function() {
debugger;
let no = $(this).data('no');
let Id = this.id;
$(".preview-image.preview-show-"+no).remove();
for (var i = 0; i < filess.length; i++) {
debugger;
filess = $.grep(filess, function(value) {
return value.name != Id;
});
}
});
});
function readImage() {
if (window.File && window.FileList && window.FileReader) {
var files = event.target.files;
var output = $(".preview-images-zone");
for (var i = 0; i < files.length; i++) {
$.grep(filess, function (n) {
if (n.name == files[i].name) {
IsAlready = true;
}
})
if (IsAlready)
{
alert("Same Name File Exist");
$("#pro-image").val('');
IsAlready = false;
return false;
}
}
var anyWindow = window.URL || window.webkitURL;
for (var i = 0; i < files.length; i++) {
filess.push(files[i]);
var file = null;
file = files[i];
if (!file.type.match('image')) continue;
var objectUrl = anyWindow.createObjectURL(files[i]);
var html = '<div class="preview-image preview-show-' + num + '" >' +
'<div class="image-cancel" data-no="' + num + '" id="' + files[i].name + '">x</div>' +
'<div class="image-zone"><img id="pro-img-' + num + '" src="' + objectUrl + '"></div>' +
'</div>';
output.append(html);
num = num + 1;
window.URL.revokeObjectURL(files[i]);
}
$("#pro-image").val('');
}
else {
console.log('Browser not support');
}
}
$("#submit").click(function () {
event.preventDefault();
debugger;
var url = "/Administration/CreateAlbum";
var albumName = $("#AlbumName").val();
var albumDescription = $("#AlbumDescription").val();
var IsActive = $("#IsActive").val();
var filess = new Array();
var data = new FormData();
data.append('albumName', albumName);
data.append('albumDescription', albumDescription);
data.append('IsActive', IsActive);
$("#submit").prop("disabled", true);
for (var i = 0; i < filess.length; i++) {
data.append('image', filess[i] );
}
var request = $.ajax({
url: url,
enctype: 'multipart/form-data',
type: 'POST',
processData: false,
contentType: false,
cache: false,
timeout: 600000,
data: data
});
request.done(function (response) {
$("#resultCode").html(response.ResultCode);
$("#resultMessage").html(response.ResultMessage);
$('#reasonCode').val("");
$('#quantity').val("");
$('#inventoryCode').val("");
$('#unitCost').val("");
});
request.fail(function (jqXHR, textStatus) {
alert("Request failed: " + textStatus);
});
});

Uploading files to azure storage from client

I have read a lot of already existing questions on uploading a file to azure storage directly from client-side/browser. The one I am implementing is from this blog by gaurav mantri. In this blog he splits the SAS url into path and query and then append file name to the path and then stiched the query again to it. I have SAS url which doesn't have any query. I just have url like this
This SAS url has the file name also appended in it. In the blog he appends blockId and blockList etc. Do it really need to do that? If not how should I make PUT request? Just using my SAS url would work?
Update: I have included query parameter (SAS token) as "URL?SAS-TOKEN". Now I am getting error like this
Error
dll.vendor.js:44368 PUT https://triggerbackendnormal.blob.core.windows.net/backend-media/a07d312c-6…Vhgoxw/NmD2AeSo4qVhBntrI04xJo1tsqfKJA/7bmQ%3D&comp=block&blockid=undefined 400 (Value for one of the query parameters specified in the request URI is invalid.)CORS
CORS Rules Setup in portal:
JS code:
handleFileSelect(e) {
var that = this
maxBlockSize = 256 * 1024;
currentFilePointer = 0;
totalBytesRemaining = 0;
files = e.target.files;
selectedFile = files[0];
console.log(selectedFile.name)
console.log(selectedFile.size)
console.log(selectedFile.type)
var fileSize = selectedFile.size;
if (fileSize < maxBlockSize) {
maxBlockSize = fileSize;
console.log("max block size = " + maxBlockSize);
}
totalBytesRemaining = fileSize;
if (fileSize % maxBlockSize == 0) {
numberOfBlocks = fileSize / maxBlockSize;
} else {
numberOfBlocks = parseInt(fileSize / maxBlockSize, 10) + 1;
}
console.log("total blocks = " + numberOfBlocks);
// $("#fileName").text(selectedFile.name);
// $("#fileSize").text(selectedFile.size);
// $("#fileType").text(selectedFile.type);
var baseUrl = 'https://example.blob.core.windows.net/backend-m/a07d312c-6e7a-4281-9e4f-050f5afc4609.mp4?sr=b&se=2017-05-04T15%3A07%3A30Z&sp=w&sv=2016-05-31&sig=SVhgoxw/NmD2AeSo4qVhBntrI04xJo1qfKJA/7bmQ%3D'
submitUri = baseUrl
console.log(submitUri);
this.uploadFileInBlocks();
}
//var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
//currentFilePointer =+ maxBlockSize;
uploadFileInBlocks() {
if (totalBytesRemaining > 0) {
console.log("current file pointer = " + currentFilePointer + " bytes read = " + maxBlockSize);
var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
var blockId = blockIdPrefix + this.pad(blockIds.length, 6);
console.log("block id = " + blockId);
blockIds.push(btoa(blockId));
reader.readAsArrayBuffer(fileContent);
currentFilePointer += maxBlockSize;
totalBytesRemaining -= maxBlockSize;
if (totalBytesRemaining < maxBlockSize) {
maxBlockSize = totalBytesRemaining;
}
} else {
this.commitBlockList();
}
}
commitBlockList() {
var uri = submitUri + '&comp=blocklist';
console.log(uri);
var requestBody = '<?xml version="1.0" encoding="utf-8"?><BlockList>';
for (var i = 0; i < blockIds.length; i++) {
requestBody += '<Latest>' + blockIds[i] + '</Latest>';
}
requestBody += '</BlockList>';
console.log(requestBody);
$.ajax({
url: uri,
type: "PUT",
data: requestBody,
beforeSend: function (xhr) {
//xhr.setRequestHeader('x-ms-blob-content-type', selectedFile.type);
//xhr.setRequestHeader('Content-Length', requestBody.length);
},
success: function (data, status) {
console.log(data);
console.log(status);
},
error: function (xhr, desc, err) {
console.log(desc);
console.log(err);
}
});
}
pad(number, length) {
var str = '' + number;
while (str.length < length) {
str = '0' + str;
}
return str;
}
render(){
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
var uri = submitUri + '&comp=block&blockid=' + blockIds[blockIds.length - 1];
var requestData = new Uint8Array(evt.target.result);
$.ajax({
url: uri,
type: "PUT",
data: requestData,
processData: false,
beforeSend: function(xhr) {
xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
// xhr.setRequestHeader('Content-Length', requestData.length);
},
success: function (data, status) {
console.log(data);
console.log(status);
bytesUploaded += requestData.length;
var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
console.log(percentComplete)
this.uploadFileInBlocks();
},
error: function(xhr, desc, err) {
console.log(desc);
console.log(err);
}
});
}
};
return (
<label htmlFor='myInput'>
<input id="myInput" type="file" ref={(ref) => this.upload = ref} style={{visibility: 'hidden'}} onChange={this.handleFileSelect.bind(this)}/>
<FloatingActionButton
className="floatingButton"
backgroundColor='#fb802a'
onClick={(e) => this.upload.click() }>
<ContentAdd />
</FloatingActionButton>
</label>
)
}
I have SAS url which doesn't have any query. I just have url like this
'https://exapmplename.blob.core.windows.net/backend/a074281-9e4f-050f5afc4609.mp4'
This is not a SAS URL. It is simply a URL for the blob. A SAS URL has Shared Access Signature parameters like sig, se, sv etc. appended to the URL as querystring parameters. I would suggest you create a SAS URL and use that. In order to upload a blob, the SAS URL must have Write permission.
In the blog he appends blockId and blockList etc. Do it really need to
do that?
It depends! If you're uploading blob without splitting the file in blocks using Put Blob REST API, then you need not do that. However if you need to split the file into blocks and use Put Block and Put Block List REST API, then you have to do that.
If not how should I make PUT request?
If your file is small and have good Internet speed, then you really need not split the file in smaller chunks and upload a file in one go using Put Blob REST API.
For ReactJS, this is how it should be done
handleFileSelect(e) {
var that = this
maxBlockSize = 256 * 1024;
currentFilePointer = 0;
totalBytesRemaining = 0;
files = e.target.files;
selectedFile = files[0];
console.log(selectedFile.name)
console.log(selectedFile.size)
console.log(selectedFile.type)
var fileSize = selectedFile.size;
if (fileSize < maxBlockSize) {
maxBlockSize = fileSize;
console.log("max block size = " + maxBlockSize);
}
totalBytesRemaining = fileSize;
if (fileSize % maxBlockSize == 0) {
numberOfBlocks = fileSize / maxBlockSize;
} else {
numberOfBlocks = parseInt(fileSize / maxBlockSize, 10) + 1;
}
console.log("total blocks = " + numberOfBlocks);
// $("#fileName").text(selectedFile.name);
// $("#fileSize").text(selectedFile.size);
// $("#fileType").text(selectedFile.type);
var baseUrl = 'https://example.blob.core.windows.net/backend-media/e7581d7b-a59d-47eb-b8aa-6b6799179b36.mp4?sv=2016-05-31&sr=b&se=2017-05-09T18%3A26%3A07Z&sp=w&sig=TlS/a9RgVT/j7BHztjFZSF2L2skno3Sko%3D'
submitUri = baseUrl
console.log(submitUri);
this.uploadFileInBlocks();
}
loadEnd(evt){
var that = this;
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
var uri = submitUri + '&comp=block&blockid=' + blockIds[blockIds.length - 1];
var requestData = new Uint8Array(evt.target.result);
$.ajax({
url: uri,
type: "PUT",
data: requestData,
processData: false,
beforeSend: function(xhr) {
xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
// xhr.setRequestHeader('Content-Length', requestData.length);
},
success: function (data, status) {
console.log(data);
console.log("hi" + status);
bytesUploaded += requestData.length;
var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
console.log(percentComplete)
that.uploadFileInBlocks();
},
error: function(xhr, desc, err) {
console.log(desc);
console.log(err);
}
});
}
}
uploadFileInBlocks() {
if (totalBytesRemaining > 0) {
console.log("current file pointer = " + currentFilePointer + " bytes read = " + maxBlockSize);
var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
var blockId = blockIdPrefix + this.pad(blockIds.length, 6);
console.log("block id = " + blockId);
blockIds.push(btoa(blockId));
reader.readAsArrayBuffer(fileContent);
reader.onloadend = this.loadEnd.bind(this);
currentFilePointer += maxBlockSize;
totalBytesRemaining -= maxBlockSize;
if (totalBytesRemaining < maxBlockSize) {
maxBlockSize = totalBytesRemaining;
}
} else {
this.commitBlockList();
}
}
commitBlockList() {
var uri = submitUri + '&comp=blocklist';
console.log(uri);
var requestBody = '<?xml version="1.0" encoding="utf-8"?><BlockList>';
for (var i = 0; i < blockIds.length; i++) {
requestBody += '<Latest>' + blockIds[i] + '</Latest>';
}
requestBody += '</BlockList>';
console.log(requestBody);
$.ajax({
url: uri,
type: "PUT",
data: requestBody,
beforeSend: function (xhr) {
//xhr.setRequestHeader('x-ms-blob-content-type', selectedFile.type);
//xhr.setRequestHeader('Content-Length', requestBody.length);
},
success: function (data, status) {
console.log(data);
console.log("hi" + status);
},
error: function (xhr, desc, err) {
console.log(desc);
console.log(err);
}
});
}
pad(number, length) {
var str = '' + number;
while (str.length < length) {
str = '0' + str;
}
return str;
}
render(){
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
var uri = submitUri + '&comp=block&blockid=' + blockIds[blockIds.length - 1];
var requestData = new Uint8Array(evt.target.result);
$.ajax({
url: uri,
type: "PUT",
data: requestData,
processData: false,
beforeSend: function(xhr) {
xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
// xhr.setRequestHeader('Content-Length', requestData.length);
},
success: function (data, status) {
console.log(data);
console.log(status);
bytesUploaded += requestData.length;
var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
console.log(percentComplete)
this.uploadFileInBlocks();
},
error: function(xhr, desc, err) {
console.log(desc);
console.log(err);
}
});
}
};
return (

Significance of '&' Symbol in JavaScript

I am currently working on a form that posts data to SAP. I am using JavaScript to invoke a Web Service to do this. I am running into an issue where one of the fields in the form has the value of 'GT&N' and I only get an error when the '&' symbol is present. I have looked on Google but have found nothing in relation the the & Symbol and JavaScript.
Error Message I'm receiving from the Web Page:
Unexpected end of file. Following elements are not closed: Characteristic_Value, RunParameter, Run, Body, Envelope. Line 1, position 2520
**The 'Characteristic_Value' is my field within the form.
Error I see when I debug:
Whenever I do not use the '&' Symbol, everything works great. I also tried using other special charecters and it posts just fine.
There is quite a bit of code to this so I am not going to post all of it unless requested as this is just a general question in regards to the '&' Symbol and JavaScript.
The JavaScript Code
//Create
var WebServer = "http://webserver";
var WebServiceName = "CreateIngredient";
var ScriptType = "Transaction";
var RepeatingTableXMLPath = "/my:myFields/my:CreateIngredient/my:CreateIngredient_Repeat";
// To Call Web service from infopath
function CreateIngredient(theXmlNode) {
//Add parameter into the request
var addBatchRequest = new SOAPClientParameters();
var Addresses = new Array();
var AddressXmlNodes = theXmlNode.selectNodes(RepeatingTableXMLPath);
// Loop for Input Field from Repeating Table
for (var i = 0; i < AddressXmlNodes.length; i++) {
var xPath = AddressXmlNodes[i].getXPath();
// Input field, It can be n number of fields
addBatchRequest.add("Material_description", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Material_description").getValue());
addBatchRequest.add("Base_Unit_of_Measure", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Base_Unit_of_Measure").getValue());
addBatchRequest.add("Material_group", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Material_group").getValue());
addBatchRequest.add("External_Material_Group", AddressXmlNodes[i].selectSingleNode(xPath + "/my:External_Material_Group").getValue());
addBatchRequest.add("Division", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Division").getValue());
addBatchRequest.add("Authorization_Group", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Authorization_Group").getValue());
addBatchRequest.add("Gross_weight", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Gross_weight").getValue());
addBatchRequest.add("Weight_Unit", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Weight_Unit").getValue());
addBatchRequest.add("Net_weight", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Net_weight").getValue());
addBatchRequest.add("Dangerous_Goods_Indicator_Profile", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Dangerous_Goods_Indicator_Profile").getValue());
addBatchRequest.add("Class_number", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Class_number").getValue());
addBatchRequest.add("Characteristic_Value", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Characteristic_Value").getValue().toString());
addBatchRequest.add("Class_number1", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Class_number1").getValue());
addBatchRequest.add("Plant", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Plant").getValue());
addBatchRequest.add("Checking_Group_for_Availability_Check", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Checking_Group_for_Availability_Check").getValue());
addBatchRequest.add("Batch_management_requirement_indicator", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Batch_management_requirement_indicator").getValue());
addBatchRequest.add("Transportation_group", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Transportation_group").getValue());
addBatchRequest.add("Loading_group", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Loading_group").getValue());
addBatchRequest.add("Profit_Center", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Profit_Center").getValue());
addBatchRequest.add("Purchasing_group", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Purchasing_group").getValue());
addBatchRequest.add("Plant-Specific_Material_Status", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Plant-Specific_Material_Status").getValue());
addBatchRequest.add("Tax_indicator_for_material__Purchasing_", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Tax_indicator_for_material__Purchasing_").getValue());
addBatchRequest.add("Indicator___automatic_purchase_order_allowed_", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Indicator___automatic_purchase_order_allowed_").getValue());
addBatchRequest.add("Purchasing_Value_Key", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Purchasing_Value_Key").getValue());
addBatchRequest.add("Storage_location", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Storage_location").getValue());
addBatchRequest.add("Temperature_conditions_indicator", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Temperature_conditions_indicator").getValue());
addBatchRequest.add("Label_type", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Label_type").getValue());
addBatchRequest.add("Label_form", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Label_form").getValue());
addBatchRequest.add("Minimum_remaining_shelf_life", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Minimum_remaining_shelf_life").getValue());
addBatchRequest.add("Total_shelf_life", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Total_shelf_life").getValue());
addBatchRequest.add("Storage_percentage", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Storage_percentage").getValue());
addBatchRequest.add("Documentation_required_indicator", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Documentation_required_indicator").getValue());
addBatchRequest.add("QM_in_Procurement_is_Active", AddressXmlNodes[i].selectSingleNode(xPath + "/my:QM_in_Procurement_is_Active").getValue());
addBatchRequest.add("Control_Key_for_Quality_Management_in_Procurement", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Control_Key_for_Quality_Management_in_Procurement").getValue());
addBatchRequest.add("Valuation_Class", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Valuation_Class").getValue());
addBatchRequest.add("Price_control_indicator", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Price_control_indicator").getValue());
addBatchRequest.add("Price_unit", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Price_unit").getValue());
addBatchRequest.add("Standard_price", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Standard_price").getValue());
addBatchRequest.add("Price_unit_for_valuation_prices_based_on_tax_commercial_law", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Price_unit_for_valuation_prices_based_on_tax_commercial_law").getValue());
addBatchRequest.add("Material-related_origin", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Material-related_origin").getValue());
addBatchRequest.add("Variance_Key", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Variance_Key").getValue());
addBatchRequest.add("Lot_Size_for_Product_Costing", AddressXmlNodes[i].selectSingleNode(xPath + "/my:Lot_Size_for_Product_Costing").getValue());
// Output field has been field with text Retrieving... in Gray color for presentation purpose only
var LogFieldNode = AddressXmlNodes[i].selectSingleNode(xPath + "/my:LogField");
var txtLog = document.getElementById("SV_" + LogFieldNode.getAttribute("SVFormElementId"));
txtLog.value = "Retrieving...";
txtLog.style.color = 'Gray';
// Final web service call parameter
var pl = new SOAPClientParameters();
pl.add("RunParameter", addBatchRequest.toXml());
pl.toXml();
SOAPClient.invoke(WebServer + "/formsservice.svc/basic", "Run", pl, true, CreateIngredient_callBack, i);
}
}
// To display the retrieved result in the proper output fields
function CreateIngredient_callBack(u, xmlresponse, RowNumber) {
var theXmlNode1 = SVFormInternalGetProperXmlNode(SVForms[0]);
var AddressXmlNodes1 = theXmlNode1.selectNodes(RepeatingTableXMLPath);
var xPath = AddressXmlNodes1[RowNumber].getXPath();
var LogFieldNode = AddressXmlNodes1[RowNumber].selectSingleNode(xPath + "/my:LogField");
var txtLog = document.getElementById("SV_" + LogFieldNode.getAttribute("SVFormElementId"));
txtLog.style.color = "";
txtLog.value = "";
if (u == null)
alert("No data retrieved for Row Number " + (RowNumber + 1) + ".");
else {
//Display result in repeating table
if (u.LogField) {
LogFieldNode.setValue(u.LogField);
document.getElementById("SV_" + LogFieldNode.getAttribute("SVFormElementId")).value = u.LogField;
}
}
}
///////////////////// Do not modify below this line ///////////////////////////////
var WsdlResult = null;
//Helping method: To build xml
function SOAPClientParameters() {
var _pl = new Array();
this.add = function (name, value) {
_pl[name] = value;
return _pl;
}
this.toXml = function () {
var xml = "";
for (var p in _pl) {
if (typeof (_pl[p]) != "function")
xml += "<" + p + ">" + _pl[p].toString() + "</" + p + ">";
}
return xml;
}
}
function SOAPClientRepeatingParametersXml(name, values) {
var xml = "";
for (var i = 0; i < values.length; i++) {
xml += "<" + name + ">" + values[i].toString() + "</" + name + ">";
}
return xml;
}
function SOAPClient() { }
SOAPClient.invoke = function (url, method, parameters, async, callback, RowNumber) {
if (async)
SOAPClient._loadWsdl(url, method, parameters, async, callback, RowNumber);
else
return SOAPClient._loadWsdl(url, method, parameters, async, callback, RowNumber);
}
// private: wsdl cache
SOAPClient_cacheWsdl = new Array();
// private: invoke async
SOAPClient._loadWsdl = function (url, method, parameters, async, callback, RowNumber) {
// load from cache?
var wsdl = SOAPClient_cacheWsdl[url];
if (wsdl + "" != "" && wsdl + "" != "undefined")
return SOAPClient._sendSoapRequest(url, method, parameters, async, callback, wsdl, RowNumber);
// get wsdl
var xmlHttp = SOAPClient._getXmlHttp();
xmlHttp.open("GET", url + "?wsdl", async);
if (async) {
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4)
SOAPClient._onLoadWsdl(url, method, parameters, async, callback, xmlHttp, RowNumber);
}
}
xmlHttp.send(null);
if (!async)
return SOAPClient._onLoadWsdl(url, method, parameters, async, callback, xmlHttp, RowNumber);
}
SOAPClient._onLoadWsdl = function (url, method, parameters, async, callback, req, RowNumber) {
var wsdl = req.responseXML;
SOAPClient_cacheWsdl[url] = wsdl; // save a copy in cache
return SOAPClient._sendSoapRequest(url, method, parameters, async, callback, wsdl, RowNumber);
}
SOAPClient._sendSoapRequest = function (url, method, parameters, async, callback, wsdl, RowNumber) {
// get namespace
try {
var ns = "http://servername.com/server/";
// build SOAP request
var sr =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
'xmlns:api="http://IPAddress/Integrics/Enswitch/API" ' +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
"xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<soap:Body>" +
"<" + method + " xmlns=\"" + ns + "\">" +
parameters.toXml() +
"</" + method + "></soap:Body></soap:Envelope>";
// send request
var xmlHttp = SOAPClient._getXmlHttp();
xmlHttp.open("POST", url, async);
var soapaction = ((ns.lastIndexOf("/") != ns.length - 1) ? ns + "/" : ns) + method;
xmlHttp.setRequestHeader("SOAPAction", "http://servername.com/server/I" + ScriptType + "Service/Process(" + WebServiceName + ")");
xmlHttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
if (async) {
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4)
SOAPClient._onSendSoapRequest(method, async, callback, wsdl, xmlHttp, RowNumber);
}
}
xmlHttp.send(sr);
}
catch (ex) { }
if (!async)
return SOAPClient._onSendSoapRequest(method, async, callback, wsdl, xmlHttp, RowNumber);
}
SOAPClient._onSendSoapRequest = function (method, async, callback, wsdl, req, RowNumber) {
var o = null;
var nd = SOAPClient._getElementsByTagName(req.responseXML, method + "Result");
if (nd.length == 0) {
if (req.responseXML.getElementsByTagName("faultcode").length > 0);
alert(req.responseXML.getElementsByTagName("faultstring") [0].childNodes[0].nodeValue);
}
else
o = SOAPClient._soapresult2object(nd[0], wsdl);
if (callback)
callback(o, req.responseXML, RowNumber);
if (!async)
return o;
}
// private: utils
SOAPClient._getElementsByTagName = function (document, tagName) {
try {
// trying to get node omitting any namespaces (latest versions of MSXML.XMLDocument)
return document.selectNodes(".//*[local-name()=\"" + tagName + "\"]");
}
catch (ex) { }
// old XML parser support
return document.getElementsByTagName(tagName);
}
SOAPClient._soapresult2object = function (node, wsdl) {
return SOAPClient._node2object(node, wsdl);
}
SOAPClient._node2object = function (node, wsdl) {
// null node
if (node == null)
return null;
// text node
if (node.nodeType == 3 || node.nodeType == 4)
return SOAPClient._extractValue(node, wsdl);
// leaf node
if (node.childNodes.length == 1 && (node.childNodes[0].nodeType == 3 || node.childNodes[0].nodeType == 4))
return SOAPClient._node2object(node.childNodes[0], wsdl);
var isarray = SOAPClient._getTypeFromWsdl(node.nodeName, wsdl).toLowerCase().indexOf("arrayof") != -1;
// object node
if (!isarray) {
var obj = null;
if (node.hasChildNodes())
obj = new Object();
for (var i = 0; i < node.childNodes.length; i++) {
var p = SOAPClient._node2object(node.childNodes[i], wsdl);
obj[node.childNodes[i].nodeName] = p;
}
return obj;
}
// list node
else {
// create node ref
var l = new Array();
for (var i = 0; i < node.childNodes.length; i++)
l[l.length] = SOAPClient._node2object(node.childNodes[i], wsdl);
return l;
}
return null;
}
SOAPClient._extractValue = function (node, wsdl) {
var value = node.nodeValue;
switch (SOAPClient._getTypeFromWsdl(node.parentNode.nodeName, wsdl).toLowerCase()) {
default:
case "s:string":
return (value != null) ? value + "" : "";
case "s:boolean":
return value + "" == "true";
case "s:int":
case "s:long":
return (value != null) ? parseInt(value + "", 10) : 0;
case "s:double":
return (value != null) ? parseFloat(value + "") : 0;
case "s:datetime":
if (value == null)
return null;
else {
value = value + "";
value = value.substring(0, value.lastIndexOf("."));
value = value.replace(/T/gi, " ");
value = value.replace(/-/gi, "/");
var d = new Date();
d.setTime(Date.parse(value));
return d;
}
}
}
SOAPClient._getTypeFromWsdl = function (elementname, wsdl) {
var ell = wsdl.getElementsByTagName("s:element"); // IE
if (ell.length == 0)
ell = wsdl.getElementsByTagName("element"); // MOZ
for (var i = 0; i < ell.length; i++) {
if (ell[i].attributes["name"] + "" == "undefined") // IE
{
if (ell[i].attributes.getNamedItem("name") != null && ell[i].attributes.getNamedItem("name").nodeValue == elementname && ell[i].attributes.getNamedItem("type") != null)
return ell[i].attributes.getNamedItem("type").nodeValue;
}
else // MOZ
{
if (ell[i].attributes["name"] != null && ell[i].attributes["name"].value == elementname && ell[i].attributes["type"] != null)
return ell[i].attributes["type"].value;
}
}
return "";
}
// private: xmlhttp factory
SOAPClient._getXmlHttp = function () {
try {
if (window.XDomainRequest) {
var req = new window.XDomainRequest();
if (req.readyState == null) {
req.readyState = 1;
req.addEventListener("load",
function () {
req.readyState = 4;
if (typeof req.onreadystatechange == "function")
req.onreadystatechange();
},
false);
}
return req;
}
}
catch (ex) {
try {
if (window.XMLHttpRequest) {
var req = new XMLHttpRequest();
// some versions of Moz do not support the readyState property and the onreadystate event so we patch it!
if (req.readyState == null) {
req.readyState = 1;
req.addEventListener("load",
function () {
req.readyState = 4;
if (typeof req.onreadystatechange == "function")
req.onreadystatechange();
},
false);
}
return req;
}
}
catch (ex) {
try {
// Internet Explorer
if (window.ActiveXObject)
return new ActiveXObject("Msxml2.XMLHTTP"); //ActiveXObject(SOAPClient._getXmlHttpProgID());
} catch (e) {
// Firefox, Opera 8.0+, Safari
try {
return new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
try {
return new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
alert("Your browser does not support AJAX!");
return false;
}
}
}
}
}
}
SOAPClient._getXmlHttpProgID = function () {
if (SOAPClient._getXmlHttpProgID.progid)
return SOAPClient._getXmlHttpProgID.progid;
var progids = ["Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
var o;
for (var i = 0; i < progids.length; i++) {
try {
o = new ActiveXObject(progids[i]);
return SOAPClient._getXmlHttpProgID.progid = progids[i];
}
catch (ex) { };
}
throw new Error("Could not find an installed XML parser");
}
Thanks in advance for any helpful input.
Cheers
Try &#38 instead of & sign.

Categories

Resources