How to use to decode data sent using AJAX in Ruby - ruby

I am very confused. I am sending my data using ajax after the information is introduced in one textarea. However, the info. is corrupted in this way: When writing pasá it would received in the server as pas%C3%A1
I already checked that pas%C3%A1 corresponds to UTF-8. URLEncode Code Chart
I also checked this link:
$('#form').serialize() messes up UTF-8 characters
but without success. This is for PHP.
Question: How can I decode UTF-8 in Ruby? or how can I avoid this corrupted data
I have defined this in my view:
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /
To get the info. from my view and to send it to the server I use:
$('textarea').change(function(e){
var pointer = $(this);
//Compare colors when focus is lost, if orange==orange, then send data
var color = pointer.css("background-color");
if (color == 'rgb(250, 187, 0)'){
var id = pointer.attr("id");
var getNumberFromId = id.substr(2,3);
var getLanguage = id.substr(0,2);
var getKey = $("#key"+getNumberFromId).html();
var getKey = getKey.replace(" ","");
console.log(getKey);
e.stopPropagation();
pointer.css('background-color','#8Fbc8F'); // Change field to green
toServer(pointer,getKey, getLanguage);
}
});
function toServer(pointer, key, language) {
$.ajax({
type: 'POST',
url: '/translator/translate/'+language+'/'+key,
data: {data:pointer.serialize()},
success: function(data){
}
});
}

If i understand correctly then you are trying to decode it at the server side. If that is the case then you could try something like this:
require 'cgi'
s = "pas%C3%A1"
string = CGI::unescape(s)
puts string # pasá

Related

How to send a pdf file for ajax response using flask?

I am trying to display a pdf file in the browser without downloading it for the user. So currently I have a flask function that can generate a pdf file using FPDF module and I need it to be displayed to the user in a new tab.
The current flask function is
#app.route('/pdf/create', methods=['GET', 'POST'])
def create_pdf():
if not session.get('email'):
return redirect(url_for('login_page'))
email = session.get('email')
pdf = FPDF('P', 'mm', "A4")
pdf.add_page()
.... pdf making ...
pdf.output(f"pdf/mypdf.pdf")
return send_file(f"pdf/mypdf.pdf",
mimetype='application/pdf',
attachment_filename=f"My file.pdf",
as_attachment=True,
cache_timeout=-1)
I call the ajax function as
$("#viewFile").on("click",function(){
$.ajax({
url: "{{url_for('create_pdf')}}",
type: "get",
data: {text: mytext},
success: function(response) {
window.open(response);
},
error: function(xhr) {
alert("Error: Failed to save notes.");
}
});
});
With the parameter as_attachment you can specify whether the browser should save the file or offer it for display. If the value is set to False, the file should be displayed. (See documentation)
The following example also shows you how you can deliver the pdf document without saving it temporarily.
The use of AJAX is not necessary in this case. A simple anchor with a target should do the trick.
Flask (app.py)
from flask import (
Flask,
render_template,
send_file
)
from fpdf import FPDF
import io
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/pdf/create')
def create_pdf():
pdf = FPDF()
pdf.set_title('My Example PDF')
pdf.set_author('Artist Unknown')
pdf.set_subject('Creation of a PDF')
pdf.add_page()
pdf.set_font('Arial', 'B', 16)
pdf.cell(40, 10, 'Hello World')
stream = io.BytesIO(pdf.output(dest='S').encode('latin-1'))
return send_file(
stream,
mimetype='application/pdf',
attachment_filename='example.pdf',
as_attachment=False
)
HTML (templates/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
Download
</body>
</html>

Posting data to node via XMLHttpRequest

I am trying to post data to a form via XMLHttpRequest using the following code:
function submitForm(event) {
event.preventDefault();
var data = new FormData(form);
var request = new XMLHttpRequest();
request.onreadystatechange = function(e) {
var formattedEmails = Object.keys(request.responseText);
formattedEmails.forEach(function(email) {
messages.addMessage(email.to, email.subject, email.message);
});
};
request.open(form.method, form.action);
request.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
request.send(data);
}
When I do this, the data comes in like this
{ '------WebKitFormBoundarywGy70eJqwXdEVot5\r\nContent-Disposition: form-data; name':'"emails"\r\n\r\n Ben,Hernandez,b****#gmail.com\r\n Ann,M*****,a****#gmail.com\r\n \r\n------WebKitFormBoundarywGy70eJqwXdEVot5\r\nContent-Disposition: form-data; name="subject"\r\n\r\nhi {first}!\r\n------WebKitFormBoundarywGy70eJqwXdEVot5\r\nContent-Disposition: form-data; name="message"\r\n\r\nHello {first} {last} {email}\r\n------WebKitFormBoundarywGy70eJqwXdEVot5\r\nContent-Disposition: form-data; name="submit"\r\n\r\nPreview\r\n------WebKitFormBoundarywGy70eJqwXdEVot5--\r\n' }
Which appears to just be a ridiculously long string of data that I need to format somehow?. When I remove the above code and allow the form to just submit like regular to the form.action page. I get this back:
{ emails: 'Ben,Hernandez,b****#gmail.com\r\nAnn,M****,a***#gmail.com\r\n',
subject: 'hi {first}!',
message: 'Hello {first} {last} {email}',
submit: 'Preview' }
Which is definitely what I want. How do I extract that from the ridiculous string above or change my post request so I get something much more manageable.
Should note that backend is express on node.
Thanks!
I ended up abandoning doing the
var data = new FormData(form);
and just manually putting my params string together. If anyone knows how to do this, I am still interested in answers.

Django, Ajax- HttpResponse does not send json

Django 1.7.2/ python 3.4
this code is about 'like'.
if user click the 'like' button, ajax calls 'pushLike'.
if the user has liked the article before(saved inside Mysql), delete the row on table(DB).
or if the user is not liking the article, create a row and insert it on the table(DB).
after that, count how many like has beed clicked on that article.
I would like to pass the likeCnt(count) to ajax, and write it on the button.
The likeCnt has the right value(I checked it on the server mysql table).
The button color does change(white to blue, and vise versa), but the text does not change.
It seems like json does not pass to ajax. I tried passing data by 'text' type and it did worked, but i want it by json.
I've tried simplejson, json, mimetype, content_type on HttpResponse.
please help me.
view
#login_required
def pushLike(request):
pk = request.GET['writing_id']
try:
la = LikeArticles.objects.get(user = User.objects.get(username=request.user.username), article_id=pk)
if(la.is_like()):
la.delete()
likeCnt = LikeArticles.objects.filter(article_id=pk).count()
FreeBoards.objects.filter(id=pk).update(like = likeCnt)
else: #Never happens
la.like = True
la.save()
likeCnt = LikeArticles.objects.filter(article_id=pk).count()
FreeBoards.objects.filter(id=pk).update(like = likeCnt)
except ObjectDoesNotExist:
la = LikeArticles(user = User.objects.get(username=request.user.username),
article = FreeBoards.objects.get(id=pk),
like = True,
)
la.save()
likeCnt = LikeArticles.objects.filter(article_id=pk).count()
FreeBoards.objects.filter(id=pk).update(like = likeCnt)
data = {'likeCnt': likeCnt}
# return render(request, url, context)
return HttpResponse(simplejson.dumps(data), mimetype='application/javascript')
javascript
<script type="text/javascript">
$(document).ready(function(){
$('#btn-like').click(function(){
var e = $('#btn-like').css('background-color');
$.ajax({
url : '/sle/freeboards/pushLike/',
data : {'writing_id':{{writing_id}},
},
dataType : "json",
success:function(data){
alert(data.likeCnt);
if(e == 'rgb(59, 89, 152)') {
$('#btn-like').css('background-color', '#ffffff').css('color', '#000000');
$('#btn-like').text(data.likeCnt);
} else {
$('#btn-like').css('background-color', '#3b5998').css('color', '#ffffff');
$('#btn-like').text(data.likeCnt);
}
},
failure: function(data){
alert('fail!!')
}
});
});
});
</script>
you'll want to be sure to set the proper mimetype in your HttpResponse
#login_required
def pushLike(request):
...
# return json -- !!not javascript!!
return HttpResponse(simplejson.dumps(...), mimetype="application/json")
--or--
#login_required
def pushLike(request):
...
# return json -- !!not javascript!!
return JsonResponse({"your": "context dictionary"})
If that doesn't work, have you tried parsing the json with your Jquery code?
ie:
$.ajax({
...
success: function(data){
var response = $.parseJSON(data);
...
}
});
javascript might actually receiving bytes back from whatever you are serving your django app with... so instead of getting JSON back, you're actually getting string that looks like JSON. http://api.jquery.com/jquery.parsejson/

Inconsistent AJAX POST status 400 . Issues with image complexity

Our team has developed a JS HTML5 canvas based paint application. In the following code, the image data is fetched from the canvas as base 64 encoding and posted to a servlet via ajax. The data post behaves erratically. If the image is simple , as in a straight line, I get Ajax status = 200 and the image gets saved. If the image is complex, then I get a status = 400 and the data is not saved.
Why should the content of the POST create issues with posting of the data itself?
function getCode(){
var canvas = document.getElementById('imageView');
var context = canvas.getContext('2d');
// draw cloud
context.beginPath();
// save canvas image as data url
var dataURL = canvas.toDataURL();
// set canvasImg image src to dataURL
// so it can be saved as an image
document.getElementById('canvasImg').src = dataURL;
var uri= document.getElementById('canvasImg').src;
uri = uri.replace('data:image/png;base64,','');
uri = uri.replace('=', '');
uri = uri.trim();
alert("uri is "+uri);
var ajaxobject ;
if(window.XMLHttpRequest){
ajaxobject = new XMLHttpRequest();
} else if(window.ActiveXObject){
ajaxobject = new ActiveXObject("Microsoft.XMLHTTP");
}else if(window.ActiveXObject){
ajaxobject = new ActiveXObject("Msxml2.XMLHTTP");
}
ajaxobject.open("POST", "SaveImageServlet?image="+uri, true);
ajaxobject.setRequestHeader("Content-type","application/x-www-form-urlencoded");
ajaxobject.onreadystatechange = function(){
if(ajaxobject.readyState==4){
alert(ajaxobject.status);
if(ajaxobject.status==200){
alert(ajaxobject.responseText);
}}
};
ajaxobject.send(null);
}
From looking at your code, the problem seems that you're passing the data in querystring instead of using the request body (as you should be doing since you're setting the POST verb).
Your uri should look like this:
SaveImageServlet
without the question mark and the parameter. The parameter should be set in the request body. Using jquery ajax your request would look like this:
$.ajax({
contentType: 'text/plain',
data: {
"image": yourBase64string
},
dataType: 'application/json', // or whatever return dataType you want
success: function(data){
// callback in case of success
},
error: function(){
// callback in case of error
},
type: 'POST',
url: '/SaveImageServlet'
});
On server side you should be reading the data from the appropriate place. For example, if you're using .Net read it like this:
Request.Form["image"]
instead of:
Request.Querystring["image"]
This should work as intended and consistently.
#Matteo, Thanks for your help and effort. However, AJAX issue never got solved. I found a way to send the base64 image data to the servlet. Just appended it to a hidden field and sent it as a regular form field.

Zipcode to city/state look-up XML file?

Trying to find an XML file I can use in lieu of a look-up database table until we get our web hosting switched over to the right DB.
Can anyone refer me to an XML file with elements whose children have zipcodes, states, and cities? E.g.:
<zip code="98117">
<state>WA</state>
<city>Seattle</state>
</zip>
Or
<entry>
<zip>98117</zip>
<state>WA</state>
<city>Seattle</city>
</entry>
I'll be using LINQ in C# to query this data.
Check out this one, it provides several different free ones.
https://stackoverflow.com/questions/24471/zip-code-database
There is a free zip code database located at:
http://www.populardata.com
I believe its a .CSV file but you could convert it to a XML file quite easily.
Here is code to do city.state autofill based on a zipcode entered.
<script type="text/javascript">//<![CDATA[
$(function() {
// IMPORTANT: Fill in your client key
var clientKey = "js-9qZHzu2Flc59Eq5rx10JdKERovBlJp3TQ3ApyC4TOa3tA8U7aVRnFwf41RpLgtE7";
var cache = {};
var container = $("#example1");
var errorDiv = container.find("div.text-error");
/** Handle successful response */
function handleResp(data)
{
// Check for error
if (data.error_msg)
errorDiv.text(data.error_msg);
else if ("city" in data)
{
// Set city and state
container.find("input[name='city']").val(data.city);
container.find("input[name='state']").val(data.state);
}
}
// Set up event handlers
container.find("input[name='zipcode']").on("keyup change", function() {
// Get zip code
var zipcode = $(this).val().substring(0, 5);
if (zipcode.length == 5 && /^[0-9]+$/.test(zipcode))
{
// Clear error
errorDiv.empty();
// Check cache
if (zipcode in cache)
{
handleResp(cache[zipcode]);
}
else
{
// Build url
var url = "http://www.zipcodeapi.com/rest/"+clientKey+"/info.json/" + zipcode + "/radians";
// Make AJAX request
$.ajax({
"url": url,
"dataType": "json"
}).done(function(data) {
handleResp(data);
// Store in cache
cache[zipcode] = data;
}).fail(function(data) {
if (data.responseText && (json = $.parseJSON(data.responseText)))
{
// Store in cache
cache[zipcode] = json;
// Check for error
if (json.error_msg)
errorDiv.text(json.error_msg);
}
else
errorDiv.text('Request failed.');
});
}
}
}).trigger("change");
});
//]]>
Here is the API - http://www.zipcodeapi.com/Examples#example1.
You can request the content in XML via To get the data back directly in XML you can use .xml in the format in the request.
https://www.zipcodeapi.com/rest/RbdapNcxbjoCvfCv4N5iwB3L4beZg017bfiB2u9eOxQkMtQQgV9NxdyCoNCENDMZ/info.xml/90210/degrees
Will respond with
<response>
<zip_code>90210</zip_code>
<lat>34.100501</lat>
<lng>-118.414908</lng>
<city>Beverly Hills</city>
<state>CA</state>
<timezone>
<timezone_identifier>America/Los_Angeles</timezone_identifier>
<timezone_abbr>PDT</timezone_abbr>
<utc_offset_sec>-25200</utc_offset_sec>
<is_dst>T</is_dst>
</timezone>
<acceptable_city_names/>
</response>
Api docs are at https://www.zipcodeapi.com/API

Resources