Download zip file (contains xml and images) through ajax and store binary data in localstorage in IE - ajax

I was able to download the zip file (2mb) from server through ajax call and storing binary data in the web storage where as this is not working in IE (7,8,9). Below is my code.
var req = new XMLHttpRequest();
req.open('GET', filename, false);
req.onreadystatechange=function()
{
if (req.readyState == 4)
{
if(req.status!=200){
chk_file = false;
alert('Sorry, Error occured while downloading the question paper. HTTP Error Code: '+req.status);
}
}
}
if (req.overrideMimeType) {
req.overrideMimeType('text/plain; charset=x-user-defined');
} else {
req.setRequestHeader('Accept-Charset', 'x-user-defined');
}
req.send('hello');
var buffer = "";
var dbata;
try {
bdata = BinaryToArray(req.responseBody).toArray();
for (var i = 0, len = bdata.length - 1; i < len; i++) {// dbata is one byte too long. Why ???
buffer += String.fromCharCode(bdata[i] & 0xFF);
}
} catch(e) {
bdata = req.responseText;
for (var i = 0, len = bdata.length; i < len; i++) {
buffer += String.fromCharCode(bdata.charCodeAt(i) & 0xFF);
}
}
Converting Binary data to array in VB script . following is the code.
var IE_HACK = (/msie/i.test(navigator.userAgent) &&
!/opera/i.test(navigator.userAgent));
if (IE_HACK) {
var vbScript = '<scr' + 'ipt type="text/vbscript">\n'+
'<!-' + '-\n' +
'Function BinaryToArray(Binary)\n'+
' Dim i\n'+
' ReDim byteArray(LenB(Binary))\n'+
' For i = 1 To LenB(Binary)\n'+
' byteArray(i-1) = AscB(MidB(Binary, i, 1))\n'+
' Next\n'+
' BinaryToArray = byteArray\n'+
'End Function\n'+
'--' + '>\n' +
'</scr' + 'ipt>';
//$(vbScript).insertAfter("script:last");
document.write(vbScript);
Storing this buffer value in html5 web storage.
I am not getting complete content in IE where it is working in FF, Chrome.
Any help!

Maybe this can help you, but guess you solved this by now, but it might help people that sees this question
is there a cross-browser alternative to the xhr.overrideMimeType() function?
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
https://github.com/eligrey/FileSaver.js
http://stuk.github.io/jszip/

Related

how to restrict double extension while uploading file to server

fileName = inputParam.file_name.split('.')[0].toLowerCase().replace(/ /g, '') + '' + Date.now() + "." + (fileData.file.name.split('.')[1] || inputParam.file_name.split('.')[1])
filePath = filePath + fileName
This is the condition I am using.
For example it should only restrict a.jpeg.jpg or a.php.jpeg. and allow extension like a.a.jpeg or bird.tree.jpeg
var _validFilejpeg = [".jpeg", ".jpg", ".bmp", ".png",".pdf", ".txt"];
var invalid = [".php",".php5", ".pht", ".phtml", ".shtml", ".asa", ".cer", ".asax", ".swf",".xap"];
function validateForSize(oInput, minSize, maxSizejpeg) {
//if there is a need of specifying any other type, just add that particular type in var _validFilejpeg
if (oInput.type == "file") {
var sFileName = oInput.value;
var file = sFileName.match(/\d/g);
var fileExt = sFileName.substr(sFileName.length-4);
if (sFileName.length > 0) {
var blnValid = false;
for (var j = 0; j < _validFilejpeg.length; j++) {
var sCurExtension = _validFilejpeg[j];
if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length)
.toLowerCase() == sCurExtension.toLowerCase()) {
blnValid = true;
break;
}
}
if(fileExt = 'invalid'){
alert("Your document does not have a proper file extension.")
blnValid = false;
}
if(fileExt = 'file'){
alert("Your document does not have a proper file extension.")
blnValid = false;
}
if (!blnValid) {
alert("Sorry, this file is invalid, allowed extension is: " + _validFilejpeg.join(", "));
oInput.value = "";
return false;
}
}
}
fileSizeValidatejpeg(oInput, minSize, maxSizejpeg);
}
function fileSizeValidatejpeg(fdata, minSize, maxSizejpeg) {
if (fdata.files && fdata.files[0]) {
var fsize = fdata.files[0].size /1024; //The files property of an input element returns a FileList. fdata is an input element,fdata.files[0] returns a File object at the index 0.
//alert(fsize)
if (fsize > maxSizejpeg || fsize < minSize) {
alert('This file size is: ' + fsize.toFixed(2) +
"KB. Files should be in " + (minSize) + " to " + (maxSizejpeg) + " KB ");
fdata.value = ""; //so that the file name is not displayed on the side of the choose file button
return false;
} else {
console.log("");
}
}
}
<input type="file" onchange="validateForSize(this,20,5000);" >
You can simply do this
if (fileName.split('.').length > 2) {
throw new Error('Double extension file detected')
}

Ajax request fails in JBOSS EAP 7.1 in Java EAR application

I've EAR applications which run fine in JBOSS EAP 6.3. When I run this application in EAP 7, then ajax call response is empty after few call. Mainly jsp page calls servlet using ajax. I use common code snippet for AJAX call. I can get response properly first 3/4 times. After that it is not working. The whole thing is working fine in EAP 6.3.
The ajax code snippet is as follows:
try{
objXMLHTTP = new XMLHttpRequest();
}catch(e){
try {
objXMLHTTP = new ActiveXObject("MSXML2.XMLHTTP.3.0");
}
catch(e){
try {
objXMLHTTP = new ActiveXObject("MSXML2.XMLHTTP");
}
catch(e) {
try {
objXMLHTTP = new ActiveXObject("Microsoft.XMLHTTP");
}
catch(e) {
alert("XMLHTTP Not Supported On Your Browser");
return;
}
}
}
}
var urlstr = "" ;
var key = "";
var j = 0;
//dataStore is an array of key/value pair.
for(key in dataStore){
if(j == 0) {
urlstr += key + "=" + dataStore[key];
j = 1;
} else {
urlstr += "&" + key + "=" + dataStore[key];
}
}
var _dateTime = new Date().getTime();
urlstr += "&CALLTIME=" + _dateTime + "-";
var requNumber = "?requNumber=" + _dateTime;
// http request has been changed as Parameterised
var _AsyncRequest = true;
try{
if(_httpMode == "undefined")
_httpMode = "0";
}catch(e){
_httpMode = "0";
}
if((_httpMode != "undefined") && (_httpMode != null) && (_httpMode == "1"))
{
_AsyncRequest = false;
}
if(!document.all)
{
_AsyncRequest = false;
}
if(urlstr.length<=1000) {
objXMLHTTP.open("POST","XMLDHTTPServlet" + requNumber + "&" + urlstr,false);
} else {
objXMLHTTP.open("POST","XMLDHTTPServlet" + requNumber,false);
}
urlstr = URLEncode(urlstr);
objXMLHTTP.setRequestHeader("content-type", "application/x-www-form-urlencoded") ;
//The following is not working after few calls
if(urlstr.length<=1000) {
objXMLHTTP.send("");
} else {
objXMLHTTP.send(urlstr);
}
rtnXML = objXMLHTTP.responseText;
if (objXMLHTTP.statusText == "OK" )
// This condition fails after successive requests
{
//Code
}
Following is in JSP page to call the AJAX. Most importantly, when I put the character **|**, then response in empty and objXMLHTTP.statusText shows Bad Request in EAP 7. But EAP 6, it is working fine.
var objXMLApplet = new xmlHTTPValidator();
objXMLApplet.clearMap();
objXMLApplet.setValue("Package", "panaceaFLweb.getMenuInfo.ReadInfo");
objXMLApplet.setValue("ValidateToken","true");
objXMLApplet.setValue("Method", "chkEODStatus");
objXMLApplet.setValue("BRNCH_CODE",BranCode);
objXMLApplet.setValue("CURR_BUSS_DATE",CBD);
objXMLApplet.setValue("DataTypes","S|S");
objXMLApplet.sendAndReceive();
It is because character | present in URL post request and didn't encode the string which length is less than 1000. Just use
urlstr = URLEncode(urlstr);
before if/else condition of connection open.
Code snippet are as follows:
urlstr = URLEncode(urlstr);
if(urlstr.length<=1000) {
objXMLHTTP.open("POST","XMLDHTTPServlet" + requNumber + "&" + urlstr,false);
} else {
objXMLHTTP.open("POST","XMLDHTTPServlet" + requNumber,false);
}
objXMLHTTP.setRequestHeader("content-type", "application/x-www-form-urlencoded") ;
if(urlstr.length<=1000) {
objXMLHTTP.send("");
} else {
objXMLHTTP.send(urlstr);
}
rtnXML = objXMLHTTP.responseText;
And URLEncode function definition are as follows:
function URLEncode(urlstr ){
var SAFECHARS = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "-_.!~*'()=?&";
var HEX = "0123456789ABCDEF";
var plaintext = urlstr;
var encoded = "";
for (var i = 0; i < plaintext.length; i++ ) {
var ch = plaintext.charAt(i);
if (ch == " "){
encoded += "+";
}else if (SAFECHARS.indexOf(ch) != -1) {
encoded += ch;
}else {
var charCode = ch.charCodeAt(0);
if (charCode > 255) {
encoded += "+";
}else {
encoded += "%";
encoded += HEX.charAt((charCode >> 4) & 0xF);
encoded += HEX.charAt(charCode & 0xF);
}
}
}
return encoded;
}

Custom HTTPRequestHandler for public file upload

I'm trying to add a HTTPRequestHandler for a public file upload service to wakanda server. Anybody should be able to POST a file to this service without logging in. Unfortunately I get a "403 Forbidden" error on all POST requests made to the HTTPRequestHandler? GET requests work fine but do not not help much in this case ;-)
The intention is to receive the file, process it, and send it back to the client.
Added my request handler as follows:
application.addHttpRequestHandler('^/fileUpload$', './backend/httpRequestHandler/file-upload.js', 'fileUpload');
Any help on how to solve this problem would be much appreciated.
Finally got it to work myself with cURL. Looks like there was some issue with my Postman setup.
cURL command:
curl --form "fileupload=#test.xml" http://localhost:8081/fileUpload
HTTPRequestHandler:
/**
* file upload handler
* #param request {HTTPRequest} http request
* #param response {HTTPResponse} http response
*/
function fileUpload(request, response) {
try {
var counter = 1;
var nameTemp;
var files = [];
var uploadFolder = Folder('/PROJECT/database/data/tmp/');
var result = [];
var newName;
var myBinaryStream;
// create upload folder if not existing
if (!uploadFolder.exists) {
uploadFolder.create();
}
// create file instances
for (var i = 0; i < request.parts.length; i++) {
files.push(new File(uploadFolder.path + request.parts[i].fileName.replace(/\s/g, '_')));
// create result object
result[i] = {};
result[i].name = request.parts[i].fileName;
result[i].type = request.parts[i].mediaType;
result[i].size = request.parts[i].size;
}
// write file content
for (var i = 0; i < files.length; i++) {
counter = 1;
if (!files[i].exists) {
myBinaryStream = BinaryStream(files[i], 'Write');
myBinaryStream.putBlob(request.parts[i].asBlob);
myBinaryStream.close();
} else {
while (files[i].exists) {
nameTemp = files[i].name.replace(/\s/g, '_');
files[i] = new File(uploadFolder.path + files[i].nameNoExt.replace(/\s/g, '_') + counter + '.' + files[i].extension);
newName = files[i].name;
if (files[i].exists) {
files[i] = new File(uploadFolder.path + nameTemp);
}
counter++;
}
myBinaryStream = BinaryStream(files[i], 'Write');
myBinaryStream.putBlob(request.parts[i].asBlob);
myBinaryStream.close();
result[i].name = newName;
}
}
result = JSON.stringify(result);
// add response header
response.contentType = 'application/json';
return result;
} catch (e) {
console.log(e.stack);
return e;
}
}

Get variable from web page with javascript in C++ Builder

I have a MiFi modem (Huawei e5776) which comes with its own web page that displays total traffic per month. I want to extract this value and display a meter in the icon tray. I'm sure this is possible in C++ Builder (or Delphi) but even though I'm pretty experienced in using C++ Builder, I am not in anything web related. Can someone give me some pointers how to do this? I assume I need to run the script and then extract the variable somewhere, how do I do this?
Thanks.
PS: I'd add the contents of the page but can't see a way to attach a document. Here's the first few lines..
// JavaScript Document
var g_monitoring_traffic_statistics = null;
var g_wlan_security_settings = null;
var g_wlan_basic_settings = null;
var g_connection_trafficresponse = null;
//Prefix string of ssid2 of Multi-SSID
var g_prefixWifiSsid = "ssid2_";
function getTrafficInfo(bit) {
var final_number = 0;
var final_str = "";
if(g_monitoring_dumeter_kb > bit) {
final_number = formatFloat(parseFloat(bit), 2);
final_str = final_number + " B";
}
else if(g_monitoring_dumeter_kb <= bit && g_monitoring_dumeter_mb > bit) {
final_number = formatFloat(parseFloat(bit) / g_monitoring_dumeter_kb, 2);
final_str = final_number + " KB";
}
else if(g_monitoring_dumeter_mb <= bit && g_monitoring_dumeter_gb > bit) {
final_number = formatFloat((parseFloat(bit) / g_monitoring_dumeter_mb), 2);
final_str = final_number + " MB";
}
else if(g_monitoring_dumeter_gb <= bit && g_monitoring_dumeter_tb > bit) {
final_number = formatFloat((parseFloat(bit) / g_monitoring_dumeter_gb), 2);
final_str = final_number + " GB";
}
else {
final_number = formatFloat((parseFloat(bit) / g_monitoring_dumeter_tb), 2);
final_str = final_number + " TB";
}
return final_str;
}
I suggest you to use a great html wrapper (named BCB HTML) for mshtml writed specially for C++Builder; With this wrapper you can execute java script inside C++ Builder cpp codes:
THTMLDocument document;
document.create();
document.write(
"<html><body><script>"
"function myFunc(n)"
"{"
"return n * n;"
"}"
"</script></body></html>");
document.parentWindow.execScript("alert(myFunc(3))", "javascript");
For your jscript:
String value = document.parentWindow.execScript("getTrafficInfo(1024)", "javascript");
Also it is possible to handle html events inside BCB, access html objects , ...
you can download it from here.
To use this source add html.cpp to your project.
If you use TWebBrowser to load a html page, you need just define document in global scope and write below code to connect/attach document variable to WebBrowser1->Document:
void __fastcall TForm1::WebBrowser1DocumentComplete(TObject *ASender,
const IDispatch *pDisp, const OleVariant &URL)
{
document.documentFromVariant(WebBrowser1->Document);
String value = document.parentWindow.execScript("getTrafficInfo(1024)", "javascript");
}

HTML5 video from MVC3 action not working correctly

I'm serving video from an MVC3 site, with the controller action that returns the video returning a FilePathResult, and when trying to play back in the browser, I'm seeing some frustrating issues, regardless of my using video.js or mediaelement.js.
Chrome doesn't let you change the position using progressbar, nor does it allow you to replay the video once it has completed
IE9 seems relatively fine
Firefox doesn't show the elapsed/remaining time correctly
However, if I just give a relative path to the file being hosted, it all works fine.
The videos need to be available only to users who belong to certain roles, so that isn't really an option.
The Action:
[Authorize]
public ActionResult Video(string fileName)
{
var pathBase = Server.MapPath("~/Downloads/Videos/");
var filePath = pathBase + fileName;
var contentType = ContentType(fileName);
return new FilePathResult(filePath, contentType) { FileDownloadName = fileName };
}
The Razor:
<!-- #t = the video entity -->
<video width="640" height="360" id="#t.Id" poster="#Url.Action("Video", "Download", new { fileName = #t.Poster })" controls="controls" preload="none">
<!-- MP4 source must come first for iOS -->
<source src="#Url.Action("Video", "Download", new { fileName = #t.Mp4 })" type='video/mp4' />
<!-- WebM for Firefox 4 and Opera -->
<source src="#Url.Action("Video", "Download", new { fileName = #t.WebM })" type='video/webm' />
<!-- OGG for Firefox 3 -->
<source src="#Url.Action("Video", "Download", new { fileName = #t.Ogv })" type='video/ogg' />
<!-- Fallback flash player for no-HTML5 browsers with JavaScript turned off -->
<object width="640" height="360" type="application/x-shockwave-flash" data="#Url.Content("~/Content/flashmediaelement.swf")">
<param name="movie" value="#Url.Content("~/Content/flashmediaelement.swf")" />
<param name="flashvars" value="controls=true&poster=#Url.Action("Video", "Download", new { fileName = #t.Poster })&file=#Url.Action("Video", "Download", new { fileName = #t.Mp4 })" />
<!-- Image fall back for non-HTML5 browser with JavaScript turned off and no Flash player installed -->
<img src="#Url.Action("Video", "Download", new { fileName = #t.Poster })" width="640" height="360" alt="#t.Title"
title="No video playback capabilities" />
</object>
</video>
I ended up writing an HTTP Handler to deal with these extensions, though it seems Chrome's issue is to do with my handler not supporting Range requests.
I used the following blog post to help me out: http://blogs.visigo.com/chriscoulson/easy-handling-of-http-range-requests-in-asp-net/. The solution (modified by me to include content type, as well as some basic security) is as follows:
public void ProcessRequest(HttpContext context)
{
if (!context.Request.RequestContext.HttpContext.User.Identity.IsAuthenticated)
context.Response.Redirect("~");
var path =
context.Request.RequestContext.HttpContext.Server.MapPath(
context.Request.AppRelativeCurrentExecutionFilePath);
long size, start, end, length, fp = 0;
using (StreamReader reader = new StreamReader(path))
{
size = reader.BaseStream.Length;
start = 0;
end = size - 1;
length = size;
// Now that we've gotten so far without errors we send the accept range header
/* At the moment we only support single ranges.
* Multiple ranges requires some more work to ensure it works correctly
* and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2
*
* Multirange support annouces itself with:
* header('Accept-Ranges: bytes');
*
* Multirange content must be sent with multipart/byteranges mediatype,
* (mediatype = mimetype)
* as well as a boundry header to indicate the various chunks of data.
*/
context.Response.AddHeader("Accept-Ranges", "0-" + size);
context.Response.ContentType = "video/mp4";
// header('Accept-Ranges: bytes');
// multipart/byteranges
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2
if (!String.IsNullOrEmpty(context.Request.ServerVariables["HTTP_RANGE"]))
{
long anotherStart = start;
long anotherEnd = end;
string[] arr_split =
context.Request.ServerVariables["HTTP_RANGE"].Split(new char[] {Convert.ToChar("=")});
string range = arr_split[1];
// Make sure the client hasn't sent us a multibyte range
if (range.IndexOf(",") > -1)
{
// (?) Shoud this be issued here, or should the first
// range be used? Or should the header be ignored and
// we output the whole content?
context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
throw new HttpException(416, "Requested Range Not Satisfiable");
}
// If the range starts with an '-' we start from the beginning
// If not, we forward the file pointer
// And make sure to get the end byte if spesified
if (range.StartsWith("-"))
{
// The n-number of the last bytes is requested
anotherStart = size - Convert.ToInt64(range.Substring(1));
}
else
{
arr_split = range.Split(new char[] {Convert.ToChar("-")});
anotherStart = Convert.ToInt64(arr_split[0]);
long temp = 0;
anotherEnd = (arr_split.Length > 1 && Int64.TryParse(arr_split[1].ToString(), out temp))
? Convert.ToInt64(arr_split[1])
: size;
}
/* Check the range and make sure it's treated according to the specs.
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
*/
// End bytes can not be larger than $end.
anotherEnd = (anotherEnd > end) ? end : anotherEnd;
// Validate the requested range and return an error if it's not correct.
if (anotherStart > anotherEnd || anotherStart > size - 1 || anotherEnd >= size)
{
context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
throw new HttpException(416, "Requested Range Not Satisfiable");
}
start = anotherStart;
end = anotherEnd;
length = end - start + 1; // Calculate new content length
fp = reader.BaseStream.Seek(start, SeekOrigin.Begin);
context.Response.StatusCode = 206;
}
}
// Notify the client the byte range we'll be outputting
context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
context.Response.AddHeader("Content-Length", length.ToString());
// Start buffered download
context.Response.WriteFile(path, fp, length);
context.Response.Flush();
}
Thanks for your answer!
I used something similar:
internal static void StreamVideo(string fullpath, HttpContextBase context)
{
long size, start, end, length, fp = 0;
using (StreamReader reader = new StreamReader(fullpath))
{
size = reader.BaseStream.Length;
start = 0;
end = size - 1;
length = size;
// Now that we've gotten so far without errors we send the accept range header
/* At the moment we only support single ranges.
* Multiple ranges requires some more work to ensure it works correctly
* and comply with the spesifications: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2
*
* Multirange support annouces itself with:
* header('Accept-Ranges: bytes');
*
* Multirange content must be sent with multipart/byteranges mediatype,
* (mediatype = mimetype)
* as well as a boundry header to indicate the various chunks of data.
*/
context.Response.AddHeader("Accept-Ranges", "0-" + size);
// header('Accept-Ranges: bytes');
// multipart/byteranges
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.2
if (!String.IsNullOrEmpty(context.Request.ServerVariables["HTTP_RANGE"]))
{
long anotherStart = start;
long anotherEnd = end;
string[] arr_split = context.Request.ServerVariables["HTTP_RANGE"].Split(new char[] { Convert.ToChar("=") });
string range = arr_split[1];
// Make sure the client hasn't sent us a multibyte range
if (range.IndexOf(",") > -1)
{
// (?) Shoud this be issued here, or should the first
// range be used? Or should the header be ignored and
// we output the whole content?
context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
throw new HttpException(416, "Requested Range Not Satisfiable");
}
// If the range starts with an '-' we start from the beginning
// If not, we forward the file pointer
// And make sure to get the end byte if spesified
if (range.StartsWith("-"))
{
// The n-number of the last bytes is requested
anotherStart = size - Convert.ToInt64(range.Substring(1));
}
else
{
arr_split = range.Split(new char[] { Convert.ToChar("-") });
anotherStart = Convert.ToInt64(arr_split[0]);
long temp = 0;
anotherEnd = (arr_split.Length > 1 && Int64.TryParse(arr_split[1].ToString(), out temp)) ? Convert.ToInt64(arr_split[1]) : size;
}
/* Check the range and make sure it's treated according to the specs.
* http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
*/
// End bytes can not be larger than $end.
anotherEnd = (anotherEnd > end) ? end : anotherEnd;
// Validate the requested range and return an error if it's not correct.
if (anotherStart > anotherEnd || anotherStart > size - 1 || anotherEnd >= size)
{
context.Response.ContentType = MimeMapping.GetMimeMapping(fullpath);
context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
throw new HttpException(416, "Requested Range Not Satisfiable");
}
start = anotherStart;
end = anotherEnd;
length = end - start + 1; // Calculate new content length
fp = reader.BaseStream.Seek(start, SeekOrigin.Begin);
context.Response.StatusCode = 206;
}
}
// Notify the client the byte range we'll be outputting
context.Response.AddHeader("Content-Range", "bytes " + start + "-" + end + "/" + size);
context.Response.AddHeader("Content-Length", length.ToString());
// Start buffered download
context.Response.WriteFile(fullpath, fp, length);
context.Response.End();
}

Resources