How to resolve error while implementing Jquery.SpellChecker in .net application - javascript

I tried to implement Jquery.Spell.Checker in asp.net application but it gives error as shown in following image.
Anyone suggest me how to resolve it.
CLICK HERE TO SEE THE SAMPLE
PS:
I have done changes in my application but still doesn't working and display alert message as per above image.Please let me know if i was missing something.The code given below:
LINK:
<link href="JQuerySpellChecker/spellchecker.css" rel="stylesheet" type="text/css" />
<script src="JavaScript/jquery-1.4.4.min.js" type="text/javascript"></script>
<script src="JQuerySpellChecker/jquery.spellchecker.js" type="text/javascript"></script>
CSS:
<style type="text/css">
body {
margin: 1em;
font-family: 'lucida grande',helvetica,verdana,arial,sans-serif;
}
#textarea-example {
width: 562px;
}
textarea {
font-size: 90%;
margin-bottom:10px;
padding: 5px;
border: 1px solid #999999;
border-color: #888888 #CCCCCC #CCCCCC #888888;
border-style: solid;
height: 20em;
width: 550px;
}
button {
font-size: 90%;
cursor: pointer;
}
.loading {
padding: 0.5em 8px;
display: none;
font-size: small;
}
</style>
HTML:
<div id="textarea-example">
<p>
<label for="text-content">Add your own text and check the spelling.</label>
</p>
<textarea id="text-content" rows="5" cols="25"></textarea>
<div>
<button id="check-textarea">Check Spelling</button>
<span class="loading">loading..</span>
</div>
</div>
JAVASCRIPT:
// check the spelling on a textarea
$("#check-textarea").click(function(e){
e.preventDefault();
$(".loading").show();
$("#text-content")
.spellchecker({
url: "CheckSpelling.aspx", // default spellcheck url
lang: "en", // default language
engine: "google", // pspell or google
addToDictionary: false, // display option to add word to dictionary (pspell only)
wordlist: {
action: "after", // which jquery dom insert action
element: $("#text-content") // which object to apply above method
},
suggestBoxPosition: "below", // position of suggest box; above or below the highlighted word
innerDocument: false // if you want the badwords highlighted in the html then set to true
})
.spellchecker("check", function(result){
// spell checker has finished checking words
$(".loading").hide();
// if result is true then there are no badly spelt words
if (result) {
alert('There are no incorrectly spelt words.');
}
});
});
// you can ignore this; if document is viewed via subversion in google code then re-direct to demo page
if (/jquery-spellchecker\.googlecode\.com/.test(window.location.hostname) && /svn/.test(window.location)) {
window.location = 'http://spellchecker.jquery.badsyntax.co.uk/';
}
CheckSpelling.aspx
protected void Page_Load(object sender, EventArgs e)
{
string str = Request["str"];
//string str = "goood";
if (str != null)
{
string url = "https://www.google.com";
string path = "/tbproxy/spell?lang=en&hl=en";
// setup XML request
string xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
xml += "<spellrequest textalreadyclipped=\"0\" ignoredups=\"0\" ignoredigits=\"1\" ignoreallcaps=\"1\">";
xml += "<text>" + str + "</text></spellrequest>";
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] data = encoding.GetBytes(xml);
WebProxy objWP = new WebProxy("address", 1978);
objWP.Credentials = new NetworkCredential("mysystemname", "password");
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url + path);
request.Proxy = objWP;
request.Method = "POST";
request.ContentType = "text/xml";
request.ContentLength = data.Length;
System.IO.Stream stream = request.GetRequestStream();
// Send the data.
stream.Write(data, 0, data.Length);
stream.Close();
// Get the response.
System.Net.WebResponse response = request.GetResponse();
// Get the stream containing content returned by the server.
stream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
System.IO.StreamReader reader = new System.IO.StreamReader(stream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Clean up the streams.
reader.Close();
stream.Close();
response.Close();
Response.ContentType = "text/xml";
MatchCollection result = Regex.Matches(responseFromServer, "<c o=\"([^\"]*)\" l=\"([^\"]*)\" s=\"([^\"]*)\">([^<]*)</c>");
if (result != null && result.Count > 0)
Response.Write(result[0].Value);
}
Response.Write("Failed");
}

You need to write yourself an ASP version of the included PHP server side file. Essentially, the server side component proxies a request off to Google or uses a PHP spell checker. Since you wouldn't really want to convert the whole of the Pspell library, I would recommend simply wrapping up the call to Google's spell check site.
i.e. Create an ASPX page and add the following code to it
<%# Import Namespace="System.Xml" %>
<script language="C#" runat="server">
public void Page_Load(Object src, EventArgs e)
{
var str = Request["str"];
if (str != null)
{
var url = "https://www.google.com";
var path = "/tbproxy/spell?lang=en&hl=en";
// setup XML request
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
xml += "<spellrequest textalreadyclipped=\"0\" ignoredups=\"0\" ignoredigits=\"1\" ignoreallcaps=\"1\">";
xml += "<text>" + str + "</text></spellrequest>";
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] data = encoding.GetBytes(xml);
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url + path);
request.Method = "POST";
request.ContentType = "text/xml";
request.ContentLength = data.Length;
System.IO.Stream stream = request.GetRequestStream();
// Send the data.
stream.Write(data, 0, data.Length);
stream.Close();
// Get the response.
System.Net.WebResponse response = request.GetResponse();
// Get the stream containing content returned by the server.
stream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
System.IO.StreamReader reader = new System.IO.StreamReader(stream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Clean up the streams.
reader.Close();
stream.Close();
response.Close();
Response.ContentType = "text/xml";
MatchCollection result = Regex.Matches(responseFromServer, "<c o=\"([^\"]*)\" l=\"([^\"]*)\" s=\"([^\"]*)\">([^<]*)</c>");
if (result != null && result.Count > 0)
Response.Write(result[0].Value);
}
Response.Write("Failed");
}
</script>
Then change the call in the js to call your new aspx file rather than the 'checkspelling.php'

Might be a bit late for you, but for any one else trying to resolve this problem, Jack Yang has produced an ASP implementation of checkspelling.php it can be found at
https://github.com/jackmyang/jQuery-Spell-Checker-for-ASP.NET

The plugin only does the client-side code. You'll have to supply it with your ASP script's URL.
Read the documentation.

Related

How to access JSON data retrieved by 3rd party API in Google Chrome Console?

My website hits a 3rd party weather API which returns JSON data like below.
{
"locations": "NYC",
"temperature":"100"
...
}
I'm trying to test some logic I built on Google Chrome Dev Console. In order to do that, I first know how to access the JSON data in the console but I can't figure out where this data is saved. I tried looking into localStorage but I had no luck.
Can someone guide me how I can access this JSON data in the Chrome console? Essentially I'm trying to see where this JSON is saved under which object.
Thanks
Rep is too low so I can't comment on the other answer.
But you can just copy the json data you find in the network tab and paste it into the developer tool console area. Just do what you would normally do, like const test = (your pasted JSON). then you can access it through test.whatever.
Try this to run this code to your console and save json data variable as data: console.save(data)
(function(console){
console.save = function(data, filename){
console.log('data is '+data);
if(!data) {
console.error('Console.save: No data')
return;
}
if(!filename) filename = 'console'
if(typeof data === "object"){
data = JSON.stringify(data, undefined, 4)
}
var blob = new Blob([data], {type: 'text/json'}),
e = document.createEvent('MouseEvents'),
a = document.createElement('a')
a.download = filename+ '.json'
a.href = window.URL.createObjectURL(blob)
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':')
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
a.dispatchEvent(e)
}
})(console)
In the Chrome Dev Tools, go to the Network tab. From there you can set it to record all resources downloaded including XMLHttp (AJAX) calls, such as the one to your API.
When the JSON response comes back, you will be able to view it here. The Preview subtab when you click on the request will contain a "pretty printed" version of the JSON. The Response subtab will contain the raw response. You can also view the headers that were sent and received, replay the XHR request, etc.
Here is a functioning example of how you might explore the data in the console by adding it to the global namespace. Please remember to remove this from your code in production as it is bad practice to pollute the global namespace. Other than that, have fun! The developer tools are one of the sharpest knives in a web developer's arsenal.
var startTime = new Date().getTime();
// Create temporary global
writeLog('Creating temp global variable', 'msg-info');
var myData = null;
// Fetch options
writeLog('Defining fetch options', 'msg-info');
let options = {
method: 'GET'
};
// Make AJAX call. When complete, the temporary global will
// be populated with your JSON data.
writeLog('Making AJAX fetch call', 'msg-info');
fetch('https://jsonplaceholder.typicode.com/todos/1', options)
.then(function(response) {
if (!response.ok) {
writeLog('HTTP ERROR RECEIVED:' + response.status, 'msg-error');
throw new Error('HTTP error, status = ' + response.status);
}
writeLog('JSON Response received', 'msg-info');
return response.json();
})
.then(function(jsonData) {
writeLog('Assigning JSON to global variable', 'msg-info');
window.myData = jsonData;
writeLog('Call Successful! Data ready to be accessed in Chrome Dev Console!', 'msg-success');
document.getElementById("rawData").innerHTML = JSON.stringify(jsonData, undefined, 2);
});
// Logging function
function writeLog(msg, className) {
var node = document.createElement('li');
if (className.length > 0) {
node.className = className;
}
var currentTime = new Date().getTime();
var elapsedTime = currentTime - startTime;
var textNode = document.createTextNode(msg + ' [' + elapsedTime + ' ms]');
node.appendChild(textNode);
document.getElementById('log').appendChild(node);
startTime = currentTime;
}
code {
color: green;
font-weight: bold;
border: 1px solid green;
padding: 3px;
}
h4 {
border-bottom: 1px solid #AAA;
background-color: #333;
padding: 5px;
color: #FFF;
margin-top: 10px;
}
#log li {
font-weight: bold;
}
.msg-info {
color: #007cff;
}
.msg-error {
color: red;
}
.msg-success {
color: green;
}
#rawData {
color: red !important;
}
<html>
<body>
<h2>Client Side API Call Test</h2>
<h3>When the call returns, you may use the developer console to interact with the response stored in a global variable <code>myData</code></h3>
<h4>LIVE REQUEST LOG:</h4>
<ul id="log"></ul>
<h4>RAW DATA PREVIEW:</h4>
<pre id="rawData"></pre>
<h4>EXAMPLE CHROME CONSOLE USAGE</h4>
Try typing this in the console after the carat symbol: <code>myData.title</code>. Or you can just type <code>myData</code> to see the whole JSON object.
<br><br>
</body>
</html>
Reference: https://developers.google.com/web/tools/chrome-devtools/network-performance/reference#response

Using FormData's append method on blob object on unsupported browser

While creating an Ajax request for a user-uploaded image, I'm using a FormData() instance in the following manner:
var form_data = new FormData();
form_data.append(img_field, img_to_send, img_name);
Note that img_to_send is an object of type Blob.
My problem is this little browser compatibility caveat in the FormData MDN web docs:
XHR in Android 4.0 sends empty content for FormData with blob.
This relates to the Android browser (ver 4.0). This implies the xhr I'm attempting with FormData via append is probably going to fail in that particular browser.
My question is, what kind of alternative can I utilize to ensure the said browser is able to correctly process the xhr (a requirement of mine)? It'll be great to get an illustrative example.
And if there are no alternatives here, how do I write my code such that it only executes for browsers that support append with a blob object? Something like this?
if (window.FormData.append) {
// xhr code comes here
}
I'm quite unsure about that one.
p.s. please stick to pure JS for the purposes of answering the question.
... Not an easy task...
First question I would ask myself is if I really have to support this 7 years old browser with 0% of usage?
Feature detection:
We can now since quite recently check what a FormData contains through its get(), has(), entries(), values() etc. methods. But the first specifications and implementations didn't had these methods and hence didn't offer any mean to detect this particular flow.
I don't have such an Android 4 browser to check, but I guess they didn't had any of these methods either...
An other modern and a bit hackish way to check would be to use a ServiceWorker, which should be able to intercept a dummy request, letting you know if your Blob was well appended, but once again, ServiceWorkers didn't exist 7 years ago.
This leaves us with an ugly browser identification, rather than a feature-detection (e.g navigator.userAgent parsing). I can't advice doing so because it's so prone to err that it might be better just letting your user know it failed in your server response.
Workaround
The ability to send a generated Blob as binary through an other mean than FormData has only appeared a few months ago, and currently only Blink browsers do support it natively, and FF through a bug exploit.
This means that the only workaround for your users on Android Browser 4.xxx and for all the browsers that didn't support this method, would be to save the generated Blob on their device, and then to pick it from an <input> and send it through a normal HTML <form>, but this is assuming they will be able to even save this Blob on their device, and I can't tell for sure...
Or you could maybe send a 30% bigger base64 representation of this data.
Or, probably the best is to let them know they should update their browser because it's really dangerous to have such an old browser facing the web nowadays.
So a small recap of the less bad possibilities:
Check if FormData is available. Otherwise fallback to an ugly b64 in a <form>
Send a first time with optimal Blob as multi-part.
On server: check if the received Blob is empty. In this case, let the front-side know from a custom response.
If server said it failed, send again, this time as b64. Since the first time was empty, it should not have been a too heavy request anyway.
Hello this is a little example how to send file to server as BINARY STRING.
With this you not requrired a formData. You can send with simple POST.
Please change the url uploadFile.php to your URL. And read the comments about variables example that your server should receiving.
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div>
<input id="btnFile" type="file" accept="image/*" />
</div>
<div style="margin-top: 20px; width: 100px; border: solid 1px red">
<div id="divProgress" style="background-color: red;width: 10px; height: 5px; margin: 1px"></div>
</div>
<div style="margin-top: 20px">
<input id="btnSend" type="button" value="Send File" />
<input id= "user_id" type="hidden" value="123"/>
</div>
<script>
var btnFile = document.getElementById("btnFile");
var btnSend = document.getElementById("btnSend");
var divProgress = document.getElementById("divProgress");
var selectedFile = null;
//Register event on file selected or changed.
addEvents(btnFile, "change", function (event) {
if (event.target.files.length !== 0) {
var file = event.target.files[0];
//Check if the file is IMAGE.
if (file.type.match("image.*")) {
selectedFile = file;
} else {
selectedFile = null;
alert("Please select a IMAGE FILE");
}
} else {
selectedFile = null;
}
});
//EVENT BTN SEND.
addEvents(btnSend, "click", function () {
if (selectedFile === null) {
//Please select a file to upload.
alert("Please select the file.");
return;
}
//File reader object.
var fl = new FileReader();
//Add event to read the content file.
addEvents(fl, "load", function (evt) {
//alert(evt.target.result);
try {
//CONVERT ARRAY BUFFER TO BASE64 STRING.
var binaryString = evt.target.result;
//NOW YOU CAN SEND SIMPLE POST DATA.
var xhr = new XMLHttpRequest();
if (supportProgress(xhr)) {
addEvents(xhr, "progress", onXHRProgress);
addEvents(xhr, "loadstart", onXHRLoadStart);
addEvents(xhr, "abort", onXHRAbort);
}
xhr.open("POST", "/uploadFile.php", true);
//xhr.setRequestHeader("Content-Type", "application/json");
var user_id = document.getElementById('user_id').value;
var myData = {
uid: user_id,
fileName: selectedFile.name,
mimeType: selectedFile.type,
extension: getFileExtension(selectedFile),
contentFile: binaryString
};
xhr.send(JSON.stringify(myData));
/*
* IN YOUR SERVER SIDE YOU GET THE POST VARIABLE.
* fileName = The name of the file.
* mimeType = example "image/png"
* extension = png
* conentFile = Binary String of the content file and you can convert the Binary String to File in your disk according extension or mimeType
*/
} catch (e) {
}
});
//Read the file as arraybuffer.
fl.readAsBinaryString(selectedFile);
});
function onXHRProgress(e) {
var loaded = 0;
if (e.lengthComputable) {
if (e.loaded === e.total) {
loaded = 100;
selectedFile = null;
} else {
loaded = Math.round((e.loaded * 100) / e.total);
}
//Change the progress here.
divProgress.style.width = loaded + "px";
}
}
function onXHRLoadStart() {
divProgress.style.width = "0px";
}
function onXHRAbort() {
selectedFile = null;
}
function getFileExtension(file) {
var fileName = file.name;
var i = fileName.toString().lastIndexOf(".");
if (i !== -1) {
return fileName.toString().substring((i + 1), fileName.toString().length).toLowerCase();
} else {
return "";
}
}
function supportProgress(xhr) {
return !!(xhr && ('upload' in xhr) && ('onprogress' in xhr.upload));
}
function addEvents(obj, evtName, func) {
if (obj.addEventListener !== undefined && obj.addEventListener !== null) {
obj.addEventListener(evtName, func, false);
} else if (obj.attachEvent !== undefined && obj.attachEvent !== null) {
obj.attachEvent(evtName, func);
} else {
if (this.getAttribute("on" + evtName) !== undefined) {
obj["on" + evtName] = func;
} else {
obj[evtName] = func;
}
}
}
function removeEvents(obj, evtName, func) {
if (obj.removeEventListener !== undefined && obj.removeEventListener !== null) {
obj.removeEventListener(evtName, func, false);
} else if (obj.detachEvent !== undefined && obj.detachEvent !== null) {
obj.detachEvent(evtName, func);
} else {
if (this.getAttribute("on" + evtName) !== undefined) {
obj["on" + evtName] = null;
} else {
obj[evtName] = null;
}
}
}
</script>
</body>
</html>

Post Base64 image to Mvc controller

Consider this base64 encode image
<img src='data:image/Png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAABICAYAAABhlHJbAAAABHNCSVQICAgIfAhkiAAAAAFzUkdCAK7OHOkAAAAEZ0FNQQAAsY8L/GEFAAAACXBIWXMAABVlAAAVZQGF3cVdAAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAABnNJREFUeF7tnFls3EQYx11ucQshClWbtb1LC4RLIARIHAXxgsQDCOWhJGs7mypIoII4BAIhsYAEWY+TlEo8FAQSQjxAuR54AnFUFHH0CQlEEWcaQhpKmx5poVWb8H3eb92Jd7Nre8a7a2d/0l9txvN99vw1HnvtGSsdqskYzu2ayb4A7dNN9oNm2E8qPW8fT5s71EOznDwYdxQ0x0s12LtXD248kaoFpFg8TisMX6Gb9t264dwHSR5PtEz7Mc10BrE92b6RnKLMLaGWulDPO+w3ryLoje8FMlG37As1094IQX/7k6RJqsl+wdNz2WDxVDXProWyGX8dv+qamFu34WQwbz1UPOIPTLec3+HfndXltQU9+P0qE1Vr9GzY+K2/MugACAfUd8q9Mslir4M+BMO+oXb52xpYaOLq1cUTyLziKVCIJvGVtmYMdlf4gTMZ4NkGpjq+NoeTwZ51k8EA+zS/AcaG5z13U0o2zy6FtoqO8ZNKpm/0AvgP350Z7SO1kHlTXJujalqB3vZApQCvSti1aT+pJGcOdUNbZZiHegtP308qBXCJfoL2k0q6+p1LYNzbwRkgoumca />
I would like to post this src to Mvc controller but getting null when post with ajax here is the post method.
var file = document.getElementById("base64image").src;
var formdata = new FormData();
formdata.append("base64image", file);
$.ajax({
url: "http://localhost:26792/home/SaveImage",
type: "POST",
data: file
});
Mvc Controller
[HttpPost]
public void SaveImage(Image file)
{
}
I think the datatype I am using is not valid for this please suggest me what can I do here.
Full Html Code
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>WebcamJS Test Page</title>
<style type="text/css">
body { font-family: Helvetica, sans-serif; }
h2, h3 { margin-top:0; }
form { margin-top: 15px; }
form > input { margin-right: 15px; }
#results { float:right; margin:20px; padding:20px; border:1px solid; background:#ccc; }
</style>
</head>
<body>
<div id="results">Your captured image will appear here...</div>
<h1>WebcamJS Test Page</h1>
<h3>Demonstrates simple 320x240 capture & display</h3>
<div id="my_camera"></div>
<!-- First, include the Webcam.js JavaScript Library -->
<script type="text/javascript" src="../webcam.min.js"></script>
<!-- Configure a few settings and attach camera -->
<script language="JavaScript">
Webcam.set({
width: 320,
height: 240,
image_format: 'jpeg',
jpeg_quality: 90
});
Webcam.attach( '#my_camera' );
</script>
<!-- A button for taking snaps -->
<form>
<input type=button id="takeshot" value="Take Snapshot" onClick="take_snapshot()">
</form>
<!-- Code to handle taking the snapshot and displaying it locally -->
<script language="JavaScript">
window.onload = function () {
setInterval(function () { take_snapshot() }, 5000);
}
function take_snapshot() {
// take snapshot and get image data
Webcam.snap( function(data_uri) {
// display results in page
document.getElementById('results').innerHTML =
'<h2>Here is your image:</h2>' +
'<img id="base64image" src="' + data_uri + '"/>';
});
var file = document.getElementById("base64image").src;
var formdata = new FormData();
formdata.append("base64image", file);
$.ajax({
url: "http://localhost:26792/home/SaveImage",
type: "POST",
data: file
});
//var ajax = new XMLHttpRequest();
//ajax.addEventListener("load", function (event) { uploadcomplete(event); }, false);
//ajax.open("POST", "http://localhost:26792/home/SaveImage");
//ajax.send(formdata);
}
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</body>
</html>
I am not 100 % sure what your end goals are here. But the below answer explains how you can send a base64 image source string to server and save it. I tested it with a base64 string generated from a small image (22 KB size) and it worked.
In your ajax call, you should be sending the FormData object you created, not the value of file variable. Also make sure you use processData and contentType properties when making the ajax call while sending a FormData object.
var file = document.getElementById("base64image").src;
var formdata = new FormData();
formdata.append("base64image", file);
$.ajax({
url: "#Url.Action("SaveImage")",
type: "POST",
data: formdata,
processData: false,
contentType: false
});
Now since this is the base 64 string of the image, use string as the parameter type of your action method. The parameter name should match with your formdata item key(base64Image). You can generate a byte array from the base64 string in your action method. Also the image source starts with data:image/png;base64, which needs to be removed from the string before you try to convert it.
The below method accepts the string you are sending from the client, and removes the first 21 characters and use the result of that (which is now a valid base 64 string) and then creates an image from that and saves to Content/Images/ directory in the app root with a random file name.
[HttpPost]
public void SaveImage(string base64image)
{
if (string.IsNullOrEmpty(base64image))
return;
var t = base64image.Substring(22); // remove data:image/png;base64,
byte[] bytes = Convert.FromBase64String(t);
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
var randomFileName = Guid.NewGuid().ToString().Substring(0, 4) + ".png";
var fullPath = Path.Combine(Server.MapPath("~/Content/Images/"), randomFileName);
image.Save(fullPath, System.Drawing.Imaging.ImageFormat.Png);
}
I am not 100 % sure that the default model binder can bind the base64 string to an image. If not, you can perhaps create one which does that and add that to the model binders in your system and then use the Image as the parameter type. The code inside model binder will be very similar ( read the string and generate image from that)
I am using HttpPostedFileBase.cs.
[HttpPost]
public ActionResult AddDocument(ReservationDocumentsVM reservationDocumentsVM, HttpPostedFileBase postedFile)
{
if (postedFile != null)
{
string path = Server.MapPath("~/Content/Documents/");
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
postedFile.SaveAs(path + Path.GetFileName(postedFile.FileName));
reservationDocumentsVM.VirtualPath = path + Path.GetFileName(postedFile.FileName);
reservationRepository.AddOrUpdateReservationDocuments(reservationDocumentsVM);
}
return RedirectToAction("Index", "Reservation");
}

Using a webservice to Create PDF only works when the service is called directly

I'm a novice with webservices, so this one has me stumped. I have created a webservice that will (eventually) accept a block of html and create a pdf file from it. To keep it simple, currently I'm not passing any parameters into the service; I'm just creating a pdf document with "hello world" in it. In debug mode, when I call the service directly (i.e. start debugging from that asmx page), I can invoke the exportPDF() method and the results are perfect -- it creates the pdf just as I'd hoped.
The problem is when I call the webservice from a javascript, nothing happens. I've set up a breakpoint inside the service, so I know it's getting called, and as I mentioned there are no parameters being passed in, so I don't understand why it works when it's invoked directly, but not when it's invoked from a javascript call.
My javascript and webservice code is below...any help would be greatly, greatly appreciated!!
Javascript:
function getPDF(elem) {
var param = { html: elem.innerHTML };
$.ajax({
type: "POST",
contentType: "application/json; charset=UTF-8",
url: "../WebServices/exporting.asmx/exportPDF",
data: "{ }",
dataType: "json",
success: function (response) {
}
})
}
WebService:
using DMC.Classes;
using NReco.PdfGenerator;
using System;
using System.IO;
using System.Web;
using System.Web.Services;
using System.Web.UI;
namespace DMC.WebServices
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class exporting : System.Web.Services.WebService
{
[WebMethod]
public void exportPDF()
{
WriteDocument("htmlToPDF.pdf", "application/pdf", ConvertHtmlToPDF());
}
public byte[] ConvertHtmlToPDF()
{
HtmlToPdfConverter nRecohtmltoPdfObj = new HtmlToPdfConverter();
nRecohtmltoPdfObj.Orientation = PageOrientation.Portrait;
nRecohtmltoPdfObj.PageFooterHtml = CreatePDFFooter();
nRecohtmltoPdfObj.CustomWkHtmlArgs = "--margin-top 35 --header-spacing 0 --margin-left 0 --margin-right 0";
return nRecohtmltoPdfObj.GeneratePdf(CreatePDFScript() + "Hello world" + "</body></html>");
}
public string CreatePDFScript()
{
return "<html><head><style>td,th{line-height:20px;} tr { page-break-inside: avoid }</style><script>function subst() {var vars={};var x=document.location.search.substring(1).split('&');for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}" +
"var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];for(var i in x) {var y = document.getElementsByClassName(x[i]);" +
"for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];}}</script></head><body onload=\"subst()\">";
}
public string CreatePDFFooter()
{
return "<div style='text-align:center;font-family:Tahoma; font-size:9px;'>Page <span class=\"page\"></span> of <span class=\"topage\"></span></div>";
}
public void WriteDocument(string fileName, string contentType, byte[] content)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = contentType;
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
HttpContext.Current.Response.CacheControl = "No-cache";
HttpContext.Current.Response.BinaryWrite(content);
HttpContext.Current.Response.Flush();
}
}
}
Thanks for the response, Mason! I've been working on this and found a solution; and while I admit it's not perfect, I don't think it's too bad. From all the different material I read, I started to get the feeling that a web service is more of a "go between" for passing data and not really meant to handle functionality like posting PDF documents. It would let you get away with it when debugging and invoking it directly, but that's about it.
So instead of using a web service, I created a class object. I also created a hidden field in my html. This field gets populated with the desired div.innerHtml content via JavaScript when somebody clicks the "Export to PDF" button. Upon postback, my codebehind checks to see if the hidden field is empty and if it isn't, it calls the exportPDF function, which in turn instantiates the class object that creates/downloads the PDF. The biggest pitfall to doing it this way, and some may consider this a big pitfall, is that to read in a field in the codebehind that has html markup in it you have to turn off validation for the web page, which obviously opens up your code for malicious attacks.
Below are the highlights of my code:
Web.Config
Add requestValidationMode = "2.0" to the web.config file
<system.web>
<httpRuntime
requestValidationMode="2.0"
targetFramework="4.5"
/>
</system.web>
.aspx Page:
Set ValidateRequest="false" in Page reference
<%# Page Title="Referrals" Language="C#" MasterPageFile="~/Behavior/Behavior.master" AutoEventWireup="true" CodeBehind="Referrals.aspx.cs"
Inherits="DMC.Behavior.Referrals" ClientIDMode="Static" EnableEventValidation="false" ValidateRequest="false" %>
.
.
.
<asp:LinkButton ID="LinkButton2" runat="server" OnClientClick="createPDF();">
<img src='../Images/icons/pdf.png'>PDF</asp:LinkButton>
.
.
.
<div id="export_pdf" class="pdfWidth_Portrait pdfSection" style="margin-top: 10px;" runat="server">
<div class="alert-info text-center" style="margin: 0; padding: 0;">
<table class="table table-condensed" style="margin-top: 0; padding: 30px; width: 100%;">
.
.
.
</table>
</div>
</div>
.
.
.
<asp:HiddenField ID="pdfData" runat="server" />
.
.
.
<script type="text/javascript">
function createPDF() {
document.getElementById("pdfData").value = document.getElementById("export_pdf").innerHTML;
}
</script>
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//Set the hidden pdf field to null initially
pdfData.Value = "";
}
//If this field is no longer null, it means somebody is wanting to export into PDF
if (pdfData.Value != "")
{
exportPDF();
}
}
public void exportPDF()
{
string fileName = null;
export dmc = new export();
fileName = lblLocation.Text + " Behavior Statistics YTD " + lblDate.Text;
dmc.exportPDF(fileName, "Portrait", pdfData.Value);
//PDF downloaded, reset value to ""
pdfData.Value = "";
}
Export Class
using NReco.PdfGenerator;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
namespace DMC.Classes
{
public class export
{
public void exportPDF(string fileName, string Orientation, string html)
{
HtmlToPdfConverter pdf = new HtmlToPdfConverter();
//Remove these control characters, they interfere with the formatting of the pdf document
html = html.Replace("\n", "");
html = html.Replace("\t", "");
html = html.Replace("\r", "");
switch (Orientation)
{
case "Portrait":
pdf.Orientation = PageOrientation.Portrait;
break;
case "Landscape":
pdf.Orientation = PageOrientation.Landscape;
break;
default:
pdf.Orientation = PageOrientation.Default;
break;
}
//In case needed for future
//pdf.CustomWkHtmlArgs = "--margin-top 35 --header-spacing 0 --margin-left 0 --margin-right 0";
pdf.Margins.Top = 25;
pdf.PageFooterHtml = createPDFFooter();
var pdfBytes = pdf.GeneratePdf(createPDFScript() + html + "</body></html>");
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + fileName + ".pdf");
HttpContext.Current.Response.BinaryWrite(pdfBytes);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}
private string createPDFScript()
{
return "<html><head><style>td,th{line-height:20px;} tr { page-break-inside: avoid }</style><script>function subst() {var vars={};var x=document.location.search.substring(1).split('&');for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}" +
"var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];for(var i in x) {var y = document.getElementsByClassName(x[i]);" +
"for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];}}</script></head><body onload=\"subst()\">";
}
private string createPDFFooter()
{
return "<div><table style='font-family:Tahoma; font-size:9px; width:100%'><tr><td style='text-align:left'>Research Dept|RR:mm:jpg</td><td style='text-align:right'>Page <span class=\"page\"></span> of <span class=\"topage\"></span></td></div>";
}
}
}

How to get video height and width from a MP4 URL with pure ecmascript and without browser support for h.264?

I'm writing a user script for downloading videos. The flash player of the web site use a JSON file.
The purpose of my script is to get the url of the video by downloading and parsing the video according to the web page. Currently it can download an extract the URL of the videos successfully.
The important part of the JSON file look like this :
{
"ammProfile": "AMM-HBBTV",
"version": "VF",
"versionProg": "1",
"VFO": "HBBTV",
"VMT": "mp4",
"VUR": "http://vo.llnwd.net/v2/am/HBBTV/051332-074-A_SQ_2_VF_01464306_MP4-2200_AMM-HBBTV.mp4"
}, {
"ammProfile": "AMM-HBBTV",
"version": "VF",
"versionProg": "1",
"VFO": "HBBTV",
"VMT": "mp4",
"VUR": "http://vo.llnwd.net/v2/am/HBBTV/051332-074-A_EQ_2_VF_01464315_MP4-1500_AMM-HBBTV.mp4"
}
Both URL here are about the same video, this just is just the resolution which change.
So, How I can parse the relevant metadata without downloading the whole file? The standard for the H.264 video codec is very hard to read.
you don't need to load the whole video to get the height:
function getVideoHeight(url, fnCallback){
var video=document.createElement("video");
video.autoplay=true;
video.oncanplay=function(){
fnCallback(this.offsetWidth, this.offsetHeight);
this.src="about:blank";
document.body.removeChild(video);
};
document.body.appendChild(video);
video.src=url;
}
//test:
getVideoHeight(
"http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4",
function(w,h){ alert( w+"X"+h); }
); // shows: "640X360"
You can use the Range HTTP header via XMLHttpRequest to get only a portion of the file:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
For example:
xhr.setRequestHeader ('Range', 'bytes=0-' + (fragment_size - 1))
xhr.setRequestHeader ('Content-Length', fragment_size) // This part isn't absolutely required on most (all?) browsers.
I use the xhr range header to download partial content, and then get the file info using videoconverter.js, a JS version of ffmpeg (whose license you should check if you plan to use any of this).
var videoUrl = 'https://dl.dropboxusercontent.com/u/17698405/bla.mp4';
var cmd = '-i myfile.mp4';
var args = parseArguments(cmd);
var sizeToDownload = 200*1024;
retrieveVideo(videoUrl, sizeToDownload, function(fileData) {
ffmpeg_run({
arguments: args,
files: [{
name: 'myfile.mp4',
data: fileData
}],
print: print,
printErr: print
});
});
function parseArguments(text) {
text = text.replace(/\s+/g, ' ');
var args = [];
text.split('"').forEach(function(t, i) {
t = t.trim();
if ((i % 2) === 1) {
args.push(t);
} else {
args = args.concat(t.split(" "));
}
});
return args;
}
function retrieveVideo(path, fragment_size, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", path, true);
xhr.responseType = "arraybuffer";
xhr.setRequestHeader ('Range', 'bytes=0-' + (fragment_size - 1));
xhr.onload = function (oEvent) {
var arrayBuffer = xhr.response;
if (arrayBuffer) {
callback(new Uint8Array(arrayBuffer));
}
};
xhr.send(null);
}
var textarea = document.getElementsByTagName('textarea')[0];
function print(text) {
textarea.value += '> ' + text + '\n';
}
* { box-sizing: border-box }
html,body { height: 100%; margin: 0; padding: 0; overflow: hidden }
textarea { width: 100%; height: 100%; }
<script src="https://rawgit.com/bgrins/videoconverter.js/master/build/ffmpeg-all-codecs.js"></script>
<textarea></textarea>

Categories