Apologies for what is surely a bonehead question...
I am trying to create a CSV file that looks like this:
Header1,Header2,Header3,
"Value1","Value2","Value3"
Instead, I'm getting a CSV file that looks like this:
Header1,Header2,Header3,\r\n"Value1","Value2","Value3"
How do I get my CRLF characters to actually produce line breaks in my output?
What I'm doing is making an ajax call to a WebMethod that generates a datatable from a stored proc. That datatable is then parsed out to a CSV like so:
if (!createHeaders)//I deal with the headers elsewhere in the code
{
foreach(DataColumn col in table.Columns){
result += col.ColumnName + ",";
};
result += Environment.NewLine;
}
for (int rowNum = 0; rowNum < table.Rows.Count; rowNum++)
{
for (int colNum = 0; colNum < table.Columns.Count; colNum++)
{
result += "\"" + (table.Rows[rowNum][colNum]).ToString();
result += "\",";
};
result += Environment.NewLine;
};
return result;
}
That string is then passed back to the success function of the ajax query, where it undergoes a few more transformations...
function getExportFile(sType) {
var alertType = null
$.ajax({
type: "POST",
url: "./Services/DataLookups.asmx/getExcelExport",
data: JSON.stringify({ sType: sType }),
processData: false,
contentType: "application/json; charset=utf-8",
dataType: "text",
success: function (response) {
response = replaceAll(response,"\\\"", "\"")
response = response.replace("{\"d\":\"", "")
response = response.replace("\"}", "")
download(sType + ".csv",response)
}
});
function download(filename, text) {
var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click()
document.body.removeChild(element);
}
function escapeRegExp(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}
function replaceAll(str, find, replace) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
In my debugging before the string is passed back to javascript, if I just type ?response, I get the incorrect, all-on-one-line response. However, when I type ?resonse,nq the linebreaks are recognized, and everything looks the way it should.
Also, I'm sure there is PLENTY that I'm doing wrong/stupidly here. Pointing out those instances is also appreciated.
Your header should have data:Application/octet-stream, as MIME-type instead of data:text/plain;charset=utf-8,, the reason being that as per HTTP specifications, when the content type is unknown, the recipient should treat it as type application/octet-stream.
Since you are already using the encodeURIComponent(), that seems to be the only issue remaining.
#AryKay's answer surely helped, but there was one additional issue. The string returned by the Ajax call had the\r\ns escaped into literals. Ran a
Response = response.replace (/\\r\\n/g, "\r\n")
Before passing to encodeURIComponent and it ran like a charm.
Related
I m using Jquery ajax request inside loop, all goes well till the last request. but after last request, page automatically reloads.I m not being able to understand what is happening there.
Plz review and help.
I m using asp.net web form and web services for handling ajax request.
Jquery Code:
var mainData = GetFromExcel();
function StartSaving()
{
for (i = 0; i < totalCount; i++)
{
DoPost(i);
}
}
function DoPost(i)
{
var mainCode = MainData[i].MainCode;
var noOfAllot = MainData[i].NoOfAllotment;
var CompanyCode = MainData[i].CompanyCode;
console.log(mainCode +' Company Code:'+ CompanyCode+':' + noOfAllot);
$.ajax({
url: "Allotment.asmx/DoAllotment",
data: "{MainCode:'" + mainCode + "', sNoOfAllotment:'" + noOfAllot + "',CompanyCode:'" + CompanyCode + "'}", // the data in JSON format. Note it is *not* a JSON object, is is a literal string in JSON format
dataType: 'text',
contentType: "application/json; charset=utf-8",
type: "Post",
async: false ,
success: function (res) {
console.log(res);
},
error: function (res) {
}
});
}
GetFromExcel is function that takes excelsheet and convert into json array. for that i have used xlsx.js
WebServices Code:
[WebMethod]
public String DoAllotment(string MainCode, string sNoOfAllotment, string CompanyCode)
{
JavaScriptSerializer js = new JavaScriptSerializer();
if(checkData())
return "Error";
else
return "Success";
}
this is a common pitfall.
Modify your javascript method to return false, see below:
function StartSaving() {
for (i = 0; i < totalCount; i++) {
DoPost(i);
}
return false; //This is important for not allowing button click post back
}
In The asp.Net button add OnclientClick as shown below:
<asp:button ..... OnClientClick="return StartSaving();"></asp:button>
***Everything else is perfect in your code!!!!
I have a js inside a jsp from where I want to send a json in another js.
In jsp the console.log(html_out); prints the json right.
$.ajax({
//ajax code
},
async: true
})
.done(function(html_out) {
console.log(html_out);
drawTable(html_out);
})
Output for console.log(html_out):
{ title: "hello1", name: "nam1" },{ title: "hello2", name: "nam2" }
But, in js the json doesn't put the data right inside the table i want to put them. The console.log(rowData); displays :
{
t
i
t
l
e
:
"
h
...
...
Here is my code in the js that i want to print my json:
function drawTable(data){
for (var i=0; i<data.length; i++){
drawRow(data[i]);
}
}
function drawRow(rowData) {
console.log(rowData);
var row = $("<tr />")
$("#farmacyDataTable").append(row);
row.append($("<td>" + rowData.title + "</td>"));
row.append($("<td>" + rowData.name + "</td>"));
}
As mentioned by dfsq, you have to parse the JSON string into a JavaScript object, right now you are iterating over the string
$.ajax({
//... ajax code
async: true, // Not needed, it default to async: true, async:false is deprecated
// If you add the line below, you don't need to parse the response
// dataType: 'json'
})
.done(function(html_out)
drawTable(JSON.parse(html_out));
})
If you correctly set the MIME type for the response (on the server), you will not need to call JSON.stringify
http://api.jquery.com/jquery.ajax/
dataType: The type of data that you're expecting back from the server. If none is specified, jQuery will try to infer it based on the MIME type of the response (an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string). The available types (and the result passed as the first argument to your success callback) are:
var parsed = JSON.parse(html_out);
drawTable(parsed);
Please take a look at the JSON.parse MDN page for browser compatibility.
I made some corrections to your code, you can play with it here: https://jsfiddle.net/mzf4axc0/
var jsonData=[{ title: "hello1", name: "nam1" },{ title: "hello2", name: "nam2" }];
function drawTable(data){
for (var i=0; i<data.length; i++){
drawRow(data[i]);
}
}
function drawRow(rowData) {
console.log(rowData);
var row = $("<tr /><td>" + rowData.title + "</td><td>" + rowData.name + "</td>" + "</tr>");
$("#farmacyDataTable").append(row);
}
$(document).ready(drawTable(jsonData));
I have an asp.net page.
Inside this page I have an img control/element.
I am calling an ashx page on my server.
This ashx page accepts a timestamp from the client and compares it to a timestamp stored on the server.
If the timestamps do not match then I return an image which has been converted to a byte array (in C#).
If the timestamps do not match then I return a string value of "-1".
So, this is a cut-down of my ashx page:
public void ProcessRequest (HttpContext context) {
context.Response.AddHeader("Access-Control-Allow-Origin", "*");
try
{
string clientTS = context.Request.QueryString["clientTS"];
if (clientTS == serverTS)
{
//new version available. refresh browser
context.Response.ContentType = "text/json";
string value = "-1";
context.Response.Write(value);
}
else
{
context.Response.ContentType = "image/jpg";
byte[] data = Shared.GetMobileNextFrame("par1", 0);
context.Response.BinaryWrite(data);
}
}
catch (Exception ex)
{
context.Response.ContentType = "text/json";
context.Response.Write("ERR");
}
}
And in my javascript code:
function GetImageStatus() {
finished = false;
var val = url + '/Mobile/isNewFrame.ashx?Alias=' + Alias + '&CamIndex=' + camIndex + '&Version=' + version + '&GuidLogOn=' + guidLogOn;
$.ajax({
url: val,
type: 'GET',
timeout: refreshWaitlimit,
data: lastTS,
success: function (response, status, xhr) {
var ct = xhr.getResponseHeader("content-type");
if (ct.indexOf('json') > -1) {
//no update
}
else {
try {
live1x4.src = 'data:image/bmp;base64,' + encode(response);
}
catch (err) {
alert(err);
}
}
},
error: function (jqXHR, textStatus, errorThrown) {
//handle error
}
});
}
function encode(data) {
var str = String.fromCharCode.apply(null, data);
return btoa(str).replace(/.{76}(?=.)/g, '$&\n');
}
But I get an error returned:
TypeError: Function.prototype.apply: Arguments list has wrong type
If I just apply:
live1x4.src = 'data:image/bmp;base64,' + btoa(response);
instead of:
live1x4.src = 'data:image/bmp;base64,' + encode(response);
I get this error:
InvalidCharacterError: btoa failed. the string to be encoded contains
characters outside of the Latin1 range.
I have tried using a canvas control with example code i have found on this site. I do not get an error but I also do not get an image.
I know the image is valid because my old code was point the image.src directly to the ashx handler (and i was not comparing timestamps).
I do not want to encode the byte array to base64 string on the server because that would inflate the download data.
I was wondering if I was using the wrong context.Response.ContentType but I could not see what else I could use.
What am i doing wrong?
When looking at the documentation at MDN you should pass 1 or more parameters to fromCharCode. You pass none in this line:
var str = String.fromCharCode.apply(null, data);
The syntax is:
String.fromCharCode(num1, ..., numN)
There is although the apply method as your said in comments, but you use it the wrong way. The first parameter shouldn't be null.
The syntax of that is (from Convert array of byte values to base64 encoded string and break long lines, Javascript (code golf)):
somefunction.apply(thisObj[, argsArray])
Just use
var str = String.fromCharCode.apply(data);
So use the thisObj parameter to pass the data.
I am sending a request by post using jquery ajax, but some of the words i send have + to join words like: HTA+HIPERAQUITISM+DBLR, the php recieve HTA HIPERAQUITISM DBLR changing the + by blank spaces, i post the code below. help!
function getItemInfo(itemName, itemField, itemComparative, itemTable){
var result = "";
var nombreItem = itemName;
var campoItem = itemField;
var comparativeItem = itemComparative;
var tableItem = itemTable;
$.ajax({
type: 'POST',
async: false,
url: 'modules/medicos/controller.php?fun=consul_item&nombre_item=consul_item'+
'&nombre_item='+nombreItem+
'&campo='+campoItem+
'&comparador='+comparativeItem+
'&tabla='+tableItem,
success: function(data) {
result = data.toString();
},
failure: function() {
result = "";
}
});
return result;
}//end function
This is because in a URL + means space.
You'll need to URL encode the data first before adding it to the query string.
You can use the encodeURIComponent() function to encode your value before adding it to the query string.
Once your PHP code picks it up you can then decode the value with the urldecode function
So your code should update to something like this:
url: 'modules/medicos/controller.php?fun=consul_item&nombre_item=consul_item'+
'&nombre_item='+encodeURIComponent(nombreItem)+
'&campo='+encodeURIComponent(campoItem)+
'&comparador='+encodeURIComponent(comparativeItem)+
'&tabla='+encodeURIComponent(tableItem),
Your code seems to be correct. You are passing those variables one by one (nombreItem, campoItem, comparativeItem and tableItem). So I don't really understand what you say is not working.
A suggestion to make passing data easier:
$.ajax({
type: 'POST',
async: false,
url: 'modules/medicos/controller.php',
data : ({ fun : consul_item,
nombre_item : nombreItem,
campo : campoItem,
comparador : comparativeItem,
tabla : tableItem }),
success: function(data) {
result = data;
},
failure: function() {
result = "";
}
});
If you want to pass all your info as one textual string you should do:
...
data: ({ test : consul_item + '+' + nombreItem + '+' + campoItem + '+' + comparativeItem + '+' + tableItem }),
...
When this function is hit , it does not call my function in code behind? Why could it be doing this? How can I fix this error.
$(document).ready(function() {
$('[id$=btn_Update]').click(function() {
var reten = $('[id$=txt_Reten]').val();
var i=0;
var selectValues = "";
var ProdID = new Array();
$("#lst_ProdId option").each(function() {
selectValues = selectValues + $(this).text() + ",";
ProdID[i] = $(this).text();
i++;
});
for(var j=0; j < ProdID.length;j++)
{
// alert(ProdID[j]);
}
var params = "{'ProdID':'" + ProdID + "','RetenP':'" + reten + "'}";
$.ajax({
type: "POST",
url: "/ProductPricing/Products/RetenPeriod.aspx/UpdateRetenPeriod",
data: params,
contentType: "application/json; charset=utf-8",
datatype: "json",
success: function(result) {
alert("sucess");
},
error:function(e) {
alert(e.statusText);
// if(errorThrown != null)
// alert(textStatus+ ":"+errorThrown);
// else
// alert("fail");
}
});
return false;
});
return false;
});
This is my webmethod in code behind:
[WebMethod]
public static bool UpdateRetenPeriod(string[] ProdID,string RetenP)
{
for (int i = 0; i < ProdID.Length; i++)
{
update(ProdID[i],RetenP);
}
return true;
}
You're passing your parameters as a string instead of as an object literal:
var params = "{'ProdID':'" + ProdID + "','RetenP':'" + reten + "'}";
should (almost certainly) be:
var params = {'ProdID': ProdID,'RetenP': reten};
Also, how do you know that the ajax request is not making it to the server? Have you tried tracing the HTTP requests with something like TamperData (for Firefox) or Firebug (also Firefox)?
Does it call the error method?
You need to return JSON. Not a boolean. Perhaps something like {success: true}.
Then:
success: function(data) {
if(data.success) {
...
}
else {
...
}
}
jQuery expects JSON and will throw an error if it doesn't receive well-formed JSON. Also, what is the exact response you're getting back? You can use something like Firebug to figure this out.
One more thing. Can you verify that you can successfully hit that URL? Are you able to successfully point your browser to http://your.url.here/ProductPricing/Products/RetenPeriod.aspx/UpdateRetenPeriod?
Also look at Pointy's solution. Your request is unlikely to succeed since you aren't passing in an actual object literal.
Do you have a ScriptManager defined in the markup with EnablePageMethods set to true?
Also, I believe your params line should be:
var params = "{ProdID:'" + ProdID + "', RetenP:'" + reten + "'}";
I have several functions in my own apps that do it this way. You want the value of params to look like this: "{ProdID:'1,2', RetenP:'undefined'}"
Can you place a breakpoint at alert(e.statusText); to see what the error message is?
Have u got error message.. please, try to get the error message
I think, u can use this by replacing error block
error:
function(XMLHttpRequest, textStatus, errorThrown){
alert( "Error Occured!" + errorThrown.toString());
}
I think, problems occurred in code behind method.. if in [web method] has any problem, then ajax doesn't call the method..