Uploading to Azure blob storage using Javascript fails? - javascript

I am following this tutorial to upload a video to blob storage - https://dmrelease.blob.core.windows.net/azurestoragejssample/samples/sample-blob.html#step1
I have done all of them including enabling CORS.
Currently I have set CORS to enable * for max period.
But i am still getting
Failed to load resource: the server responded with a status of 400 (Bad Request)
:9000/#/:1 Failed to load https://XXXXXX.blob.core.windows.net/3d7959e4-a48d-447b-a919-
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:9000' is
therefore not allowed access. The response had HTTP status code 400.
I had it working two days ago, but it just suddenly stopped working.
Here is my javascript on how I am calling.
var blobUri = 'https://XXXXXX.blob.core.windows.net/';
var sastoken = 'XXXXXX';
var blobService = AzureStorage.Blob.createBlobServiceWithSas(blobUri, sastoken);
var customBlockSize = file.size > 1024 * 1024 * 32 ? 1024 * 1024 * 4 : 1024 * 512;
blobService.singleBlobPutThresholdInBytes = customBlockSize;
var customediaid = mediaid;
//Guid
//Wrong guid here- create a proper one
var customazureid = guid + ".mp4";
var finishedOrError = false;
var speedSummary = blobService.createBlockBlobFromBrowserFile(
customediaid,
customazureid,
file,
{ blockSize: customBlockSize },
function (error, result, response) {
finishedOrError = true;
if (error) {
console.log(error);
alert('Failed look console');
} else {
alert('Success - Check folder named -' + mediaid + "with filename - " + customazureid + '.mp4');
UpdateDatabase(mediaid, azuremediaid);
}
}
);
Have my cors enabled like this for the storage account.
ALLOWED ORIGINS ALLOWED METHODS ALLOWED HEADERS EXPOSED HEADERS MAX AGE
* GET,HEAD,POST,PUT,OPTIONS,MERGE,DELETE * * 2147483647
Also in the tutorial website, you can list all the containers using SAS token and storage account. That also works when I add in those fields. It just wont work in my site.
Edit
Not sure if this helps, but here is how the request looks like by using the postman tool to capture them.
https://XXXXX.blob.core.windows.net/02b8be3e-22b7-41fc-a1d3-831153f8de90/97d603e4-767d-ddc2-169a-379db3af7419.mp4?comp=block&blockid=Njc4YTA4Nz
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:en-US,en;q=0.9
Access-Control-Request-Headers:content-type,x-ms-client-request-id,x-ms-date,x-ms-version
Access-Control-Request-Method:PUT
Connection:keep-alive
DNT:1
Host:XXXXXXX.blob.core.windows.net
Origin:http://localhost:9000
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Respone I get is -
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin'
header is present on the requested resource.
Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 403.

According to your description, I just reused your code with my azure blob storage as follows:
<script type="text/javascript" src="https://brucchstorage.blob.core.windows.net/scripts/azurestoragejs-0.2.8-preview/azure-storage.blob.js"></script>
<script type="text/javascript">
function uploadfile() {
var blobUri = 'https://brucchstorage.blob.core.windows.net';
var blobService = AzureStorage.Blob.createBlobServiceWithSas(blobUri, 'st=2018-04-04T21%3A41%3A00Z&se=2018-04-05T21%3A41%3A00Z&sp=rw&sv=2017-04-17&sr=c&sig=D1HX40pFCONuWGKTCKCYXyWvbwuErrog6yTfk%2FZBQ1A%3D');
// If one file has been selected in the HTML file input element
var file = document.getElementById('fileinput').files[0];
var customBlockSize = file.size > 1024 * 1024 * 32 ? 1024 * 1024 * 4 : 1024 * 512;
blobService.singleBlobPutThresholdInBytes = customBlockSize;
var finishedOrError = false;
var speedSummary = blobService.createBlockBlobFromBrowserFile('images', file.name, file, { blockSize: customBlockSize }, function (error, result, response) {
finishedOrError = true;
if (error) {
// Upload blob failed
alert("error:" + error);
} else {
// Upload successfully
alert("success");
}
});
}
</script>
If I do not configure the CORS for my blob storage, I would retrieve the following error:
Then, I used Azure Storage Explorer to set the CORS as follows:
TEST:
Moreover, I would recommend you open a new incognito window to narrow down this issue.

Related

Problems to get POST response JavaScript front / node js back

im trying to connect to my local node server route (http://localhost:3000/user-ragnarok-controller/saveragnarokuser/) from my javascript application and im getting no response from it. The server is receiving the request and is processing the same, but i cant get the response at client side.
my javascript app are running at localhost:80 (Apache XAMPP) and my node server at localhost:3000.
this is my javascript code to connect to node server end-point:
function handler() {
alert('handler');
if(invocation.readyState === XMLHttpRequest.DONE && invocation.status === 200) {
alert('entrei aqui');
console.log(invocation.responseText);
} else
alert('nao foi hj ' + invocation.status.toString());
}
function saveUser() {
alert('dourado ');
var eml = document.getElementById('emailInputRegister');
var user = document.getElementById('userInputText');
var sx = document.getElementById("sexInputSelected");
var selectedSex = sx.options[sx.selectedIndex].value;
var pwd = document.getElementById("passwordInputRegister");
var uri = 'http://localhost:3000/user-ragnarok-controller/saveragnarokuser/';
var body = {
'userid': user.value,
'userpass': pwd.value,
'email': eml.value,
'sex': selectedSex
};
invocation.open('POST', uri);
invocation.withCredentials = true;
invocation.setRequestHeader('Content-Type', 'application/json');
invocation.onreadystatechange = this.handler;
invocation.send(JSON.stringify(body));
}
this is my request at google chrome console
Now let's talk about the server side. Here i have a middleware for CORS treatment.
// Add headers
app.use(function (req, res, next) {
console.log('reqHeaders: ' + JSON.stringify(req.headers));
res.header('Access-Control-Allow-Origin', 'http://localhost');
res.header('Access-Control-Allow-Headers', 'content-type');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header('Access-Control-Allow-Credentials', true);
if(req.method === 'OPTIONS')
return res.status(200).send({});
next();
});
After CORS, the server starts my route POST:
router.post('/saveragnarokuser',function(req,res,next){
console.log('######################### Iniciando saveragnarokuser.');
UserRagnarokController.addUser(req.body,function(err,count){
if(err){
console.log('entrei aqui error: ' + err);
res.json(err);
}
else{
console.log('entrei aqui ok');
var userObj = {
response: "OK"
};
res.status(200).json(userObj);
}
});
});
looking to the server log its possible to see the request coming, processing, but for some reason the POST response is -- ms --. With no Status and execution time.
reqHeaders: {"host":"localhost:3000","connection":"keep-alive","content-length":"88","user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36","content-type":"application/json","accept":"*/*","origin":"http://localhost","sec-fetch-site":"same-site","sec-fetch-mode":"cors","sec-fetch-dest":"empty","referer":"http://localhost/co-cadastro/register.html?","accept-encoding":"gzip, deflate, br","accept-language":"pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7"}
######################### Iniciando saveragnarokuser.
myReqbody: {"userid":"fernandocabeca","userpass":"1234","email":"acosta.aluiz#gmail.com","sex":"F"}
POST /user-ragnarok-controller/saveragnarokuser/ - - ms - -
entrei aqui ok
My function UserRagnarokController.addUser performed perfectly, the requisition data was successfully filled in the database, i just need to get this response at client side (google chrome app), i got no error and no success.
NOTE: when I execute the request at POSTMAN it works normally, the answer is 200 OK.
There is probably a warning in the browser's console about breaking of CORS policy.
Headers about CORS should come from your server (Response Headers) and I don't see that tab here in your screenshot.
Postman ignores CORS, and server process all request by default.

No HTTP response from Chrome extension to my Java Server

This is my very first question I am posting on StackOverflow. I usually tend to find answers to any question I have for whatever project, but I am really stuck on this one. I'm writing a Chrome extension that attempts to send JSON-objects over a HTTP post request with certain data in it to a basic Java server that will -in a later stage- process some of the data and return a HTTP response with relevant (processed) information for the client. This is the relevant JavaScript snippet on client-side:
function postRequest(jsonObject) {
var param = JSON.stringify(jsonObject);
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (request.readyState == 4) {
console.log(request.response);
}
};
request.open("POST", "http://"+link);
request.setRequestHeader("Content-type","text/plain");
request.send(param);
// request.abort();
}
The input JSON-object is legit and the link-item is the predefined host IP of the server. The server-side code is Java-based and is the following:
public class Server {
public static void main(String args[]) throws Exception {
while (true) {
try {
ServerSocket ss = new ServerSocket(1024);
Socket s = ss.accept();
System.out.println("Request: ");
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw = new PrintWriter(s.getOutputStream());
String line;
while ((line = br.readLine()) != null) {
if (line.length() == 0) {
break;
}
System.out.print(line + "\r\n");
}
System.out.println("");
System.out.println("Response:");
String response = "HTTP/1.1 200 OK \r\n" + "Access-Control-Allow-Origin: * \r\n"
+ "Connection: close \r\n" + "\r\n";
System.out.println(response);
pw.write(response);
while ((line = br.readLine()) != null) {
if (line.length() == 0) {
break;
}
System.out.print(line + "\r\n");
}
br.close();
pw.close();
System.out.println("");
System.out.println("Socket Closed");
System.out.println("");
s.close();
ss.close();
} catch (Exception ex) {
// Do whatever
}
}
}}
The server does receive the request and the JSON-object, but no response is received on client side (readyState is usually 4, but status code is 0 and responseText is empty). Additionally the connection is not closed when I don't use request.abort() or close the extension's window. It for sure has nothing to do with the permissions in the manifest file, so I didn't include it in this post. Can somebody see what my mistake is or anybody have had a similar experience?
EDIT:
The HTTP request is received on server side and looks like:
POST / HTTP/1.1
Host: [IP address of the server; I deleted the exact address for privacy]
Connection: keep-alive
Content-Length: 173
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
Origin: chrome-extension://nhpingbdjkkljheamibjobneeehiednk
Content-type: text/plain
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4,fr;q=0.2
Since the request is received on server side, I figured that the actual sending of the response is currently unsuccessful. Might it have something to do with the origin domain of the client? When I copy-paste that domain in my browser, I get a ERR_FILE_NOT_FOUND.

Want to display a PDF document returned by a GET request in IE11

This is something that I feel should be very simple, but haven't been able to solve so far.
I'm working with a vendor system which has implemented a very basic API for our use. We send a GET request with an authentication token in the header, the server then returns us a PDF document in the body of the response.
All I want to do is display the PDF in the browser, any method would be fine, in a new tab or iframe etc.
I have managed to get this working in both firefox and chrome utilising the answer at: Request a file with a custom header But this does not work with IE 11, and IE11 is the only supported browser within our organisation.
Request headers are:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Authorization:bearer ZYFXVEnE2Uf3kU0Ud8rFvq5pbV2IfrNzzJBAu8lI8p73reZ6-vdeChtXlGGN7NwUNvo2-5LKNd9FniZlcElplycBL4f2qu6EaHkO-Xb_-G5DR07p62UYq_DErl937Yc-mpLMphBBHC7-0uqYNfrivkbc3xeOvEBnRRtfagz7dYJ8EJive6QjwWjYgGj9HRQUAbcOggbJGxZDXmrlWTveUji-5CKb7w5guBUOhjyDkyB53r8rm2qptGfsp1NsKLU4h4kEDlNaxbbzB_oJQbuyIoG80BTnP-NB0bqOtPJ09FrM9AFVfrdJM0fRwS3BfxRgVNm01FgW-jQwp1GgzeAbS-3uRR1G92Y-rw6L8R17l31PPFlV_CNeK_oAG-AJldmn2lgv6a6l6Cj9s2OqOfXyX09iZIN6vIKXAqedSWb708GTNfJ7iLKjdGVYCYW1zZ9IZKXMyeMoK7nW_rDuMzmoXeLY3tGFeeOf27vuI4RdSaGVCD5kIynrYPe8fU1sp-KZE0i1aJ0qqQ9g7Nvg42ZsFIFHBqhRIY-k4Dxjm1jPloGNbFqhdc-GK5LYHcg_u3DwFbSUKWpXdzCPBn43qJ_yVfDqffQDsDafvGDKP0U4duq0eYNXYWKnB8VR7xytykWjXAj70a9SFPRocqhugiqJIwBMS6a5gfqlUssgEnCfhVGE_eGUSGrYdCvfHHKb-13O9m6dXomYFuK8Ql7H73MjDgzTihtYLULh3nAHrU-FehrBRsUeKpc32hKUVhVvTlw2lTOUcMhlC99EKPMT0hZhLy4t8e-icL2aqcKdN-S1rt-HU60cukw4SnLyM_Nfa-ytD8vtUwMLAV9K5h4DdK7H3LpfbQNbaHRfBjRk5aQ7Q2o
Content-type:application/json
Host: /vendor_URL/
Origin:null
Proxy-Connection:keep-alive
User-Agent:Mozilla/5.0 (Windows NT 6.3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36
Response Headers:
Accept-Ranges:none
Access-Control-Allow-Origin:*
Cache-Control:no-cache
Content-Disposition:inline; filename=GoToPlan.pdf
Content-Length:372483
Content-Type:application/pdf
Date:Wed, 26 Oct 2016 19:41:04 GMT
Expires:-1
Pragma:no-cache
Proxy-Connection:keep-alive
Server:Microsoft-IIS/7.5
Via:1.1 /proxy_URL/
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
Code that currently works in firefox and Chrome:
var document_http = new XMLHttpRequest();
var url = /document_URL/
document_http.open("GET", url, true);
//DOn'y know why, but needs this to display correctly
document_http.overrideMimeType( "application/octet-stream; charset=x-user-defined;" );
//Send the proper header information along with the request
document_http.setRequestHeader("Content-type", "application/json");
document_http.setRequestHeader("Authorization", "bearer " + auth_response[3]);
document_http.onreadystatechange = function() {//Call a function when the state changes.
if (document_http.readyState == 4 & document_http.status == 200) {
var data = toBinaryString(this.responseText);
data = "data:application/pdf;base64,"+btoa(data);
window.open(data);
}
}
document_http.send(params);
function toBinaryString(data) {
var ret = [];
var len = data.length;
var byte;
for (var i = 0; i < len; i++) {
byte=( data.charCodeAt(i) & 0xFF )>>> 0;
ret.push( String.fromCharCode(byte) );
}
return ret.join('');
}
Data URIs are subject to browsers' limitations on URLs. You can't reliably use them to display long content.
You can load the document as a blob, then use it in a iframe:
var xhr = new XMLHttpRequest();
xhr.open("GET", "/path/to/file.pdf");
xhr.responseType = "blob";
xhr.onload = function(res) {
iframe.src = URL.createObjectURL(res.response);
};
xhr.send();
This should work in every major browser. URL.createObjectURL will create a string of the form blob:http://host/unique-id that is a reference to the blob object.
Remember to call URL.revokeObjectURL on the given string when you're done showing the PDF. This will discard the reference to the blob, which can be safely garbage collected.

Setting a custom content-type xmlhttprequest

I have an API I am trying to interface with that requires a custom content-type header be set, with the value text/xmlmc
I've implemented this like so
Xmlmc.prototype.submitRequest = function (request,callback) {
var self = this;
var port = portMap[request.service] || 5015;
var endpoint = this.endpoint = 'http://' + this.server + ':' + port;
var xml = request.toXml();
var xhttp;
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
// IE 5 and 6 makes us sad. Please don't use it
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
//handle request
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
var response = self.handleResponse(xhttp);
callback(response);
}
};
xhttp.open('POST',endpoint,true);
xhttp.setRequestHeader('Content-type', 'text/xmlmc');
//xhttp.setRequestHeader('Content-length', xml.length.toString());
if(this.sessionCookie != '') {
xhttp.setRequestHeader('Cookie', this.sessionCookie);
}
xhttp.send(xml);
};
The endpoint is localhost:5015
When I do this, the request fails and never even sends. When I use a standard request header like 'text/plain' the request is sent but returns a status code of 501 not implemented. How can I set a custom HTTP header in an xmlhttprequest?
It turns out this was due to a cross origin issue. Even when the domain is the same, if the ports are different it is a problem. I fixed the issue by adding a reverse proxy to my apache configuration and now I can query the api without cross origin requests. Unfortunately I don't have access to change the API and allow cross origin domains.

Catch too long form submission

I am developing an HTML page which has simple HTML form (nothing special) being submitted by button. There is a couple of situations when form submitted and response comes too long (if whenever really comes back). How can i organize the form the way it fires some callback when waiting a response is too long? We could show up some notice for user, indicating our server is overloaded in that situation.
Here is request that being sent by form:
POST http://example.com/search HTTP/1.1
Host: example.com
Proxy-Connection: keep-alive
Content-Length: 83
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://example.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://example.com/
Accept-Encoding: gzip, deflate
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: [cookie definition omitted]
[form data omitted]
Is Proxy-Connection: keep-alive influence the process somehow? Googling led me to https://github.com/caxap/jquery-safeform plugin, but it is for a little bit different purpose.
It depends on what type of UI you want to present to the user. You can simply lower the timeout at the server level and if it can't finish the response in time, it will abort. However, the user experience is pretty harsh, as they'll just get a generic timeout error that likely won't even be from your site. (They'll have to click back or something to get back to your site.)
If you just want to display a message after a certain amount of time has passed, you can attach to the form's submit event and use setTimeout to display an alert or something:
$('#MyForm').on('submit', function () {
setTimeout(30000, function () { // number is milliseconds
alert('Sorry this is taking so long.');
});
});
Finally, if there's some method of tracking the progress of the action that's being completed server-side, you could use something like web sockets or long-polling via AJAX to provide a progress bar or status update of some sort. That's a bit more complex, though, and will require some research on your part.
There are two approaches, I will write two separate answers.
XMLHttpRequest progress approach
(for modern browsers)
Just send data and read uploading progress from XMLHttpRequest:
//-------------upload ------------------
var lastProgressIndex = -1;
//is the file api available in this browser
//only override *if* available.
if (new XMLHttpRequest().upload) {
$("#upload-files").click(function () {
upload_files($("#files-to-upload")[0].files, lastProgressIndex++);
return false;
});
$("#files-to-upload").change(function () {
upload_files($("#files-to-upload")[0].files, lastProgressIndex++);
return false;
});
$("#upload-files").hide();
}
function resetFormElement(elem) {
elem.wrap('<form>').closest('form').get(0).reset();
elem.unwrap();
}
function clear_upload() {
//https://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
var upload = $("#files-to-upload");
//upload.replaceWith(upload = upload.clone(true));
resetFormElement(upload);
}
//accepts the input.files parameter
function upload_files(filelist) {
if (typeof filelist !== "undefined") {
for (var i = 0, l = filelist.length; i < l; i++) {
upload_file(filelist[i], lastProgressIndex++);
}
}
clear_upload();
}
//each file upload produces a unique POST
function upload_file(file, index) {
//TODO - vytvor progress bar podle indexu
$("#progresscontainer").append('<div id="progressbar' + index + '" class="progressbar"><div id="progresslabel' + index + '" class="progressbarlabel"></div></div>')
var progressBarSelector = "#progressbar" + index;
var progressLabelSelector = "#progresslabel" + index;
var fileName = file.name;
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
//update the progress bar
var percent = Math.floor((evt.loaded / evt.total) * 100) + "%";
//TODO http://www.binaryintellect.net/articles/859d32c8-945d-4e5d-8c89-775388598f62.aspx
$(progressBarSelector).css({
width: percent
});
$(progressLabelSelector).html(fileName + ' ' + percent);
}
}, false);
// File uploaded
xhr.addEventListener("load", function () {
$(progressLabelSelector).html(fileName + " uploaded");
AddImageToGallery(GetFilenameWithoutExt(fileName));
$(progressBarSelector).fadeOut(500, function () {
$(progressBarSelector).remove();
});
}, false);
var guid = $("#Identification").val();
xhr.open("post", "/uploadurl/uploadfile/" + guid, true);
// Set appropriate headers
// We're going to use these in the UploadFile method
// To determine what is being uploaded.
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.setRequestHeader("X-File-Name", file.name);
xhr.setRequestHeader("X-File-Size", file.size);
xhr.setRequestHeader("X-File-Type", file.type);
// Send the file
xhr.send(file);
}
And server part:
private UploadedFile[] RetrieveFileFromRequest()
{
List<UploadedFile> uploadedFiles = new List<UploadedFile>();
if (Request.Files.Count > 0)
{ //they're uploading the old way
for (int i = 0; i < Request.Files.Count; i++)
{
var file = Request.Files[0];
string contentType = file.ContentType;
string filename = file.FileName;
UploadedFile uploadedFile = SaveUploadedFile(file.InputStream, file.ContentLength, filename, contentType);
uploadedFiles.Add(uploadedFile);
}
}
else if (Request.ContentLength > 0)
{
string filename = Request.Headers["X-File-Name"];
string contentType = Request.Headers["X-File-Type"];
UploadedFile uploadedFile = SaveUploadedFile(Request.InputStream, Request.ContentLength, filename, contentType);
uploadedFiles.Add(uploadedFile);
}
return uploadedFiles.ToArray();
}
These sources are modification of the original article. There is related stackoverflow question.
How can I organize the form the way it fires some callback when waiting a response is too long?
This is based on your algorithm. You can estimate the time like brute force calculation and show the result before beginning to perform. It's not an optimized solution if you start processing and then break it when too many time is spent!
Update: If you can't estimate like above, At least, write an asynch controller method which is useful when an action must perform several independent long running operations. Follow this:
Write an Ajax Form with unobtrusive-ajax
Define a function for OnBegin form option to call a timer
The timer's time out event will show another thing to user.
Write an asynch controller method for the operation which
contains a timer to stop processing when it takes more
than ?? seconds.
There are two approaches, I will write two separate answers.
Sending thread/UI thread approach
You will need 2 javascript "threads".
Sending thread:
With first open websocket and start sending data to server. On the server side update some variable how many data was sent and how many remaining.
UI thread:
Using Ajax ask server frequently (HTTP request with JSON format is fine), how many data was send and how many remaining and render the progressbar in javascript.
Finnaly, when UI thread request receive information that upload is ready, remove progressbar with jquery and show message or redirect page.
With this approach you can easily show send bytes, estimation time remaining, upload speed.
So every javascript thread has corresponding server tread. And both server threads share the structure with dataSend and dataRemaining dependent on your server technology.
Bellow You can find part of my code which upload several images and show preview after finish is finished:
intervalID = window.setInterval(function()
{
var request = new Sys.Net.WebRequest();
request.set_url('UploadProgress.ashx?DJUploadStatus=' + token + '&ts=' + new Date().getTime());
request.set_httpVerb('GET');
request.add_completed(function(executor) {
// the progress is returned as xml
var e = executor.get_xml().documentElement;
var empty = e.getAttribute('empty');
if (!empty)
{
// extract the attributes I am interested in
var percent = e.getAttribute('progress');
var file = e.getAttribute('file');
var kbs = Math.round(parseInt(e.getAttribute('bytes')) / 1024);
var size = Math.round(parseInt(e.getAttribute('size')) / 1024);
// update the progressbar to the new value
progressBar.set_percentage(percent);
// upadte the message
updateMessage('info', 'Uploading ' + file + ' ... ' + kbs + ' of ' + size + ' KB');
if (percent == 100)
{
// clear the interval
window.clearInterval(intervalID);
}
}
});
// invoke the request
request.invoke();
}, 1000);
You could check for WebTimeout exception from server side then use SignalR to actively send timeout messsage back to client side:
var request = (HttpWebRequest)WebRequest.Create("http://www.your_third_parties_page.com");
request.Timeout = 1000; //Timeout after 1000 ms
try
{
using (var stream = request.GetResponse().GetResponseStream())
using (var reader = new StreamReader(stream))
{
Console.WriteLine(reader.ReadToEnd());
}
}
catch (WebException ex)
{
//Check for timeout exception
if (ex.Status == WebExceptionStatus.Timeout)
{
//If timeout then send SignalR ajax message to inform the clients...
var context = GlobalHost.ConnectionManager.GetHubContext<YourHub>();
context.Clients.All.addNewMessageToPage("This method has been processing too long!");
}
}
See more how to setup SignalR for asp.net here

Categories