I'm uploading the big files using chunk method.If i make minimum number request to the server uploading is working fine.if make high number of request to the server Chrome browser has crashed with Aw Snap! error message.But other browsers are working fine with high number of request.
How to resolve this.Is there workaround?is it chromium bug?
Updated
Below function will slice the file then upload chunk to server .After all chunks uploaded. Merge Api will merge the chunk.
Code:
function readFile (file) {
var uploadBatchKey = this.guid;
var start = 0; //Start Index
var stop = file.size; //End Index
var chunksize = (document.getElementById('chunkSize').value * 1048576);
var index = this.chunkUploadIndex;
var reader = new FileReader();
var filecontent = null;
var waitingInterval = null;
var totalsegment = Math.ceil(stop / chunksize);
var isPreviousChunkUpload = true;
var match = ko.utils.arrayFirst(JSViewmodel.SelectedFiles(), function (item) {
return item.UploadManager == undefined ? false : (uploadBatchKey === item.UploadManager.guid);
});
match.UploadBatchKey(uploadBatchKey);
var handle = setInterval(function () {
if (isPreviousChunkUpload) {
if (!match.IsUploading()) {
clearInterval(handle);
}
else if (index > totalsegment) {
isPreviousChunkUpload = false;
var filename = match.IsRelativePath() ? file.webkitRelativePath : file.name;
console.log(file.size);
var batchData = { uploadBatchKey: uploadBatchKey, fileName: filename, fileSize: file.size };
$.ajax({
url: "/Home/MergeChunk",
type: 'POST',
async: false,
data: batchData,
success: function (result) {
debugger;
console.log(result);
if (result == "False")
match.IsFailed(true);
},
error: function (result) {
console.log(result);
debugger;
match.IsFailed(true);
}
});
match.IsUploading(false);
match.IsCompleted(true);
clearInterval(handle);
}
start = (index - 1) * chunksize;
stop = (index * chunksize) - 1;
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
filecontent = evt.target.result;
var chunkContent = { chunkContent: window.btoa(filecontent), chunkIndex: index - 1, uploadBatchKey: uploadBatchKey };
console.log("onloadend" + chunkContent.chunkIndex);
$.ajax({
url: "/Home/Upload",
type: 'POST',
async: false,
data: chunkContent,
success: function (result) {
match.Percentage(Math.round((chunkContent.chunkIndex / totalsegment) * 100));
isPreviousChunkUpload = true;
}
});
}
};
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
isPreviousChunkUpload = false;
console.log("file slice:" + index);
index++;
match.UploadManager.chunkUploadIndex = index;
}
}, 500);
}
Related
On browse button click I have appended file(images) in FormData
and on Add Product button click I have to post Formdata via ajax to controller
but I am getting FromData as null on controller as well as on console.log.
Please let me know where I am going wrong.
Browse Button Click Event
$(document).ready(function () {
var _formData = new FormData();
$('.Btn_Browse').on('click', function () {
let input = document.createElement('input');
input.setAttribute('id', 'input_image')
input.setAttribute('multiple', 'multiple');
input.type = 'file';
input.onchange = _ => {
let files = Array.from(input.files);
if (files.length > 1) {
for (var i = 0; i < files.length; i++) {
_formData.append(files[i].name, files[i]);
}
};
input.click();
});
});
Add Product Button Click Event
$('#id_AddProduct').click(function (e) {
for (var key of _formData.entries()) {
console.log(key[0] + ', ' + key[1]);
}
$.ajax({
type: "POST",
url: "AddProduct",
contentType: false,
processData: false,
cache: false,
data: _formData,
success: function (response) {
},
failure: function (response) {
confirm("Your process is failed..");
},
error: function (response) {
confirm("Error occur during the process..");
}
});
});
Controller
public ActionResult AddProduct()
{
byte[] imagebyte = null;
int count = Request.Files.Count;
HttpFileCollectionBase Files = Request.Files;
for (int i = 0; i < Files.Count; i++)
{
HttpPostedFileBase httpPostedFileBase = Files[i];
if (httpPostedFileBase != null)
{
List<DALImage> imageList = new List<DALImage>();
if (Request.Files.Count > 0)
{
using (var br = new BinaryReader(httpPostedFileBase.InputStream))
{
var imgdata = br.ReadBytes(httpPostedFileBase.ContentLength);
DALImage objImg = new DALImage();
objImg.ImageName = httpPostedFileBase.FileName;
objImg.ImageTye = httpPostedFileBase.ContentType;
objImg.ImageData = Convert.ToBase64String(imgdata);
imageList.Add(objImg);
}
}
}
//string message = DAL.AddProduct(imageList, objProductDetails);
}
return Json(imagebyte, JsonRequestBehavior.AllowGet);
}
net MVC application, in which I have multiple charts. On these charts, I have applied filters and by clicking each filter, I do an ajax call which returns the result in Json and then applies to the charts.
Now its working perfectly in Firefox and Chrome, but in Internet Explorer - Ajax call is always unsuccessful. I tried hitting the web api url directly through my browser and the issue it seems is, the result json was being returned as a file to be downloaded.
This is my ajax code :
function getIssueResolvedGraphdata(control, departCode, departName) {
$.ajax(
{
type: "GET",
url: WebApiURL + "/api/home/GetQueryIssueResolvedData?deptCode=" + departCode,
dataType: "json",
crossDomain: true,
async: true,
cache: false,
success: function (myData) {
var resolvedStartDate = myData.data.IssueResolvedStartDate;
var issueData = myData.data.IssueData;
var resolveData = myData.data.ResolvedData;
//converting issueData into integer array...
var issue = issueData.replace("[", "");
var issue1 = issue.replace("]", "");
var issue2 = issue1.split(",");
for (var i = 0; i < issue2.length; i++) { issue2[i] = parseInt(issue2[i]); }
//converting resolvedData into integer array
var resolve = resolveData.replace("[", "");
var resolve1 = resolve.replace("]", "");
var resolve2 = resolve1.split(",");
for (var j = 0; j < resolve2.length; j++) { resolve2[j] = parseInt(resolve2[j]); }
//getting max value from array...
var issueMaxVal = Math.max.apply(null, issue2);
var resolveMaxVal = Math.max.apply(null, resolve2);
//Eliminating leading zeros in issue array
var removeIndex = 0;
var myDate;
var newDate;
var arrayLength;
if (issueMaxVal != 0) {
arrayLength = issue2.length;
for (var i = 0; i < arrayLength; i++) {
if (issue2[0] == 0) {
issue2.splice(0, 1);
removeIndex = i;
} else {
break;
}
}
//Getting days count of current month
var monthStart = new Date(new Date().getFullYear(), new Date().getMonth(), 1);
var monthEnd = new Date(new Date().getFullYear(), new Date().getMonth() + 1, 1);
var monthLength = (monthEnd - monthStart) / (1000 * 60 * 60 * 24);
var monthDays = 0;
if (monthLength == 28) {
monthDays = removeIndex;
}
else if (monthLength == 30) {
monthDays = removeIndex + 1;
}
else if (monthLength == 31 || monthLength == 29) {
monthDays = removeIndex + 2;
}
//matching the resultant issue array with resolve array & setting start date
var iDate = resolvedStartDate;
var tDate = '';
for (var i = 0; i < iDate.length; i++) {
if (iDate[i] == ',') {
tDate += '/';
}
else {
tDate += iDate[i];
}
}
if (removeIndex != 0) {
resolve2.splice(0, (removeIndex + 1));
var myDate = new Date(tDate);
myDate.setDate(myDate.getDate() + monthDays);
newDate = Date.UTC(myDate.getFullYear(), (myDate.getMonth() + 1), myDate.getDate());
} else {
var myDate = new Date(tDate);
newDate = Date.UTC(myDate.getFullYear(), (myDate.getMonth() + 1), myDate.getDate());
}
} else {
alert("Empty");
}
//updating chart here...
var chart = $('#performance-cart').highcharts();
chart.series[0].update({
pointStart: newDate,
data: issue2
});
chart.series[1].update({
pointStart: newDate,
data: resolve2
});
if (issueMaxVal > resolveMaxVal) {
chart.yAxis[0].setExtremes(0, issueMaxVal);
} else {
chart.yAxis[0].setExtremes(0, resolveMaxVal);
}
},
error: function (x, e) {
alert('There seems to be some problem while fetching records!');
} });}
Code from web api controller :
[HttpGet]
[CrossDomainActionFilter]
public Response<GraphIssueResolvedWrapper> GetQueryIssueResolvedData(string deptCode)
{
Response<GraphIssueResolvedWrapper> objResponse = new Response<GraphIssueResolvedWrapper>();
GraphIssueResolvedWrapper objGraphIssueResolvedWrapper = new GraphIssueResolvedWrapper();
try
{
....code.....
objResponse.isSuccess = true;
objResponse.errorDetail = string.Empty;
objResponse.data = objGraphIssueResolvedWrapper;
}
catch (Exception ex)
{
objResponse.isSuccess = false;
objResponse.errorDetail = ex.Message.ToString();
objResponse.data = null;
}
return objResponse;
}
Reponse Class :
public class Response<T>
{
public bool isSuccess { get; set; }
public string errorDetail { get; set; }
public T data { get; set; }
}
I am stuck at this for hours now. Any help will be appreciated.
I have solved my problem by using the following code : ( I guess it needed CORS support)
function isIE() {
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE");
if (msie > 0)
return true;
return false;
}
Then in document.ready function of my binding script :
$(document).ready(function () {
if (isIE())
$.support.cors = true;
});
Note : it still download Json stream as a file but now my AJAX call is successful upon each hit.
You've missed contentType: 'text/html' which is pretty important for IE7-8:
$.ajax(
{
type: "GET",
url: WebApiURL + "/api/home/GetQueryIssueResolvedData?deptCode=" + departCode,
dataType: "json",
contentType: 'text/html'
crossDomain: true,
async: true,
cache: false,
success: function (myData) {
var result = JSON.parse(myData);
///...code...
},
error: function (x, e) {
alert('There seems to be some problem while fetching records!');
}
}
);
To make it works in IE7-8 you also need to be sure that you've writing Conrent-Type Header into your response on server side. Add this line right before return statement;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html; charset=iso-8859-1");
And in code probably you will need to parse result in success method by using JSON.parse(myData);
So I'm trying to find a method of getting a progress bar working on my .ajax call but not having much luck. I know that the ajaxForm plugin has the following code in it that allows for the uploadProgress option but the way my code works I'm not able to use that plugin. Is there anyway of adding the following code somehow so that it attaches to the standard .ajax call? Long shot I know!
// XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
function fileUploadXhr(a) {
var formdata = new FormData();
for (var i=0; i < a.length; i++) {
formdata.append(a[i].name, a[i].value);
}
if (options.extraData) {
var serializedData = deepSerialize(options.extraData);
for (i=0; i < serializedData.length; i++)
if (serializedData[i])
formdata.append(serializedData[i][0], serializedData[i][1]);
}
options.data = null;
var s = $.extend(true, {}, $.ajaxSettings, options, {
contentType: false,
processData: false,
cache: false,
type: method || 'POST'
});
if (options.uploadProgress) {
// workaround because jqXHR does not expose upload property
s.xhr = function() {
var xhr = jQuery.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function(event) {
var percent = 0;
var position = event.loaded || event.position; /*event.position is deprecated*/
var total = event.total;
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
}
options.uploadProgress(event, position, total, percent);
}, false);
}
return xhr;
};
}
s.data = null;
var beforeSend = s.beforeSend;
s.beforeSend = function(xhr, o) {
o.data = formdata;
if(beforeSend)
beforeSend.call(this, xhr, o);
};
return $.ajax(s);
}
I do not guarantee on that, but try this:
xhr.upload.onprogress = function(event) {
var percent = 0;
var position = event.loaded || event.position;
var total = event.total;
if (event.lengthComputable) {
percent = Math.ceil(position / total * 100);
}
console.log("Progress: "+percent+"%"); //debug to see if the problem is there
options.uploadProgress(event, position, total, percent);
};
From posted code, I cannot even guess if the problem is in onprogress event handling or that options.uploadProgress, whatever it is.
I posted this as answer only because it wouldn't fit in comment.
I cannot seem to find out why IE does not read my success on get after the post. I have tried cache: false, with no luck. This works in all other browsers, just not IE.
$.ajaxSetup({ cache: false });
num = $('#num').val();
phone = $('#phone').val();
$.post("post.php?"+$("#MYFORM").serialize(), {
}, function(response){
if(response==1 && codeVal == 1 && telVal == 1)
{
$("#after_submit").html('');
$("#Send").after('<label class="success" id="after_submit">Η αποστολή πραγματοποιήθηκε</label>');
change_captcha();
clear_form();
$.ajax({
type:'get',
cache: false,
url: "http://web.somesite/submit_code.php",
dataType: 'html',
data:{ user: "one", pass: "mtwo", source: "WEB", receipt: num, msisdn: phone},
success: function(data) {
var qsFull = "http://web.somesite.gr/submit_code.php?" + data;
var qs = URI(qsFull).query(true);
TINY.box.show({html:qs.message,animate:false,boxid:'error',top:5});
}
});
}
else
{
$("#after_submit").html('');
$("#Send").after('<label class="error" id="after_submit">Error! in CAPTCHA .</label>');
}
});
OK, I tried adding an error after the success and I see that I get my pop up as I should be, but the value of qs.message is 0. Why would I get error and not success, when it is successful in other browsers.
I found the answer, It has to do with IE not being flexible with cross domains and such, so I added a XDomainRequest like so
if (jQuery.browser.msie && window.XDomainRequest) {
var xdr = new XDomainRequest();
var my_request_data = { user: "M1web", pass: "m!", source: "WEB", receipt: num, msisdn: phone};
my_request_data = $.param(my_request_data);
if (xdr) {
xdr.onerror = function () {
alert('xdr onerror');
};
xdr.ontimeout = function () {
alert('xdr ontimeout');
};
xdr.onprogress = function () {
alert("XDR onprogress");
alert("Got: " + xdr.responseText);
};
xdr.onload = function() {
//alert('onload ' + xdr.responseText);
var qsFull = "http://web.web.gr/submit_code.php?" + xdr.responseText;
var qs = URI(qsFull).query(true);
TINY.box.show({html:qs.message,animate:false,boxid:'error',top:5});
callback(xdr.responseText);
};
xdr.timeout = 5000;
xdr.open("get", "http://web.web.gr/submit_code.php?" + my_request_data);
xdr.send();
} else {
}
}
I unfortunately had to do a crash course in legacy IE behavior, and this post was very helpful. Here are some other links to help those having to deal with these issues:
Microsoft's Documentation of their XDomainRequest object
An internal blog post covering some of XDomainRequest's idiosyncrasies
Here's a function I use as a fallback where necessary:
// This is necessary due to IE<10 having no support for CORS.
function fallbackXDR(callObj) {
if (window.XDomainRequest) {
var xdrObj = new XDomainRequest();
xdrObj.timeout = callObj.timeout;
xdrObj.onload = function() {
handleSuccess(xdrObj.responseText);
};
xdrObj.onerror = function() {
handleError(xdrObj);
};
xdrObj.ontimeout = function() {
callObj.xdrAttempts = callObj.xdrAttempts++ || 1;
if (callObj.xdrAttempts < callObj.maxAttempts) {
fallbackXDR(callObj);
}
};
xdrObj.onprogress = function() {
// Unfortunately this has to be included or it will not work in some cases.
};
// Use something other than $.param() to format the url if not using jQuery.
var callStr = callObj ? '?'+$.param(callObj.urlVars) : '';
xdrObj.open("get", callObj.url+callStr);
xdrObj.send();
} else {
handleError("No XDomainRequest available.", callObj);
}
}//fallbackXDR()
I'm having a bit of an issue with my javascript object. What I want to do is pass in an id and have it set a variable that is accessible to all of my functions.
Here's a small sample of what I have:
var myObject = function() {
var pageSize = 6;
var currentPage = 1;
var pagerPagesVisible = 5;
var pagerId = '#my-pager';
var entityId = '';
var doStuff = function() {
var endIndex = pageSize * currentPage;
var startIndex = endIndex - pageSize;
$.ajax({ type: "GET", url: "/items/" + this.entityId + "/entities/" + startIndex + "/" + pageSize + "/", dataType: "json", success: loadData, cache: false,
error: function(response, status, error) {
alert(response.responseText);
}
});
};
var loadData = function(data) {
var itemCount = data.length;
//build the html and write to the page
buildPager(itemCount);
};
var buildPager = function(itemCount) {
pager.build(pagerId, pageSize, itemCount, currentPage);
};
var attachEvents = function() {
//attach events to the pager
};
return {
init: function(entityId) {
this.entityId = entityId;
doStuff();
}
}
} ();
the issue is, in init, it sets the entityId instance that you see at the top. But when it hits doStuff() entityId is set back to ''.
You're mixing closure and object styles - you need to be consistent:
<script>
var myObject = function() {
var pageSize = 6;
var currentPage = 1;
var pagerPagesVisible = 5;
var pagerId = '#my-pager';
var entityId = '';
var doStuff = function() {
alert(entityId);
};
return {
init: function(myEntityId) {
entityId = myEntityId;
doStuff();
}
}
} ();
myObject.init(123);
</script>
Others have answered your question here, but I wanted to point out that you may want to use the prototype if you are going to be creating many of these objects.
When you enclose your methods you waste memory on every instantiation.
ClassName.prototype.methodname = function(){ ... }
That's because the entityId variable is local to the function and has nothing to do with the object you create at the end. Instead, put everything in that object at the end and not as locals in the function.
eg.
var myObject = function() {
var pageSize = 6;
var currentPage = 1;
var pagerPagesVisible = 5;
var pagerId = '#my-pager';
return {
doStuff: function() {
var endIndex = pageSize * currentPage;
var startIndex = endIndex - pageSize;
var self = this;
$.ajax( {
type: "GET",
url: "/items/" + this.entityId + "/entities/" + startIndex + "/" + pageSize,
dataType: "json",
success: function() { self.loadData(); },
cache: false,
error: function(response, status, error) {
alert(response.responseText);
}
} );
},
loadData: function(data) {
var itemCount = data.length;
this.buildPager(itemCount);
},
buildPager = function(itemCount) {
pager.build(pagerId, pageSize, itemCount, currentPage);
},
attachEvents: function() {
//attach events to the pager
},
entityId: '',
init: function(entityId) {
this.entityId = entityId;
this.doStuff();
}
};
}();