Specification:
Server 2012
Framework 3.5
I have already deployed my webservice in the server http://ipaddress/eSignatureWS.asmx?op=SaveImg.
Problem: when i change the ajax dataType to "json" or "text" it has an Internal Server Error, but when i used "script" it won't have an error but it don't save the image. When i try it locally it works using "json"/"text" but when i deployed it won't work anymore.
So here's my code:
Jquery
function signatureSave() {
var canvas = document.getElementById("newSignature"); // save canvas image as data url (png format by default)
var data = canvas.toDataURL("image/png");
var signatureData = data.replace(/^data:image\/(png|jpg);base64,/, "");
var donum = "sampleImg"; //imagename
$.support.cors = true;
//var imgData = JSON.stringify(signatureData);
$.ajax({
type: "Post",
async: false,
url: "http://ipaddress/eSignatureWS.asmx?op=SaveImg",
data: { "filename": donum, "imgBit": signatureData },
dataType: "json",
success: function (data) { //alert(data);
if (data.match("true")) {
document.getElementById('errorImage').innerHTML = "Successfully Submitted!";
}
else {
document.getElementById('errorImage').innerHTML = "Error occured.";
}
},
error: function (XMLHttpRequest, testStatus, errorThrown) {
document.getElementById('errorImage').innerHTML = errorThrown;
alert(XMLHttpRequest + testStatus + errorThrown);
}
})
Webservice
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string SaveImg(string filename, string imgBit)
{
try
{
string filepath = WebConfigurationManager.AppSettings["ImgLocation"].ToString();
string imgPath = filepath + filename + ".png";
//creates a png image signature
using (FileStream fs = new FileStream(imgPath, FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(imgBit);
bw.Write(data);
bw.Close();
JavaScriptSerializer js = new JavaScriptSerializer();
string strJSON = js.Serialize("true");
return strJSON;
}
}
}
catch (Exception ex)
{
}
}
Check the edit section!
I'm guessing you're not aware of the "maxJsonLength" attribute which is set to 100KB by default, in ASP.NET. I wasn't aware of that till the latest search I had to make about the same subject :)
In the Web.Config file you can change this default limitation to your needs.
<configuration>
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="1000000"/>
</webServices>
</scripting>
</system.web.extensions>
</configuration>
That one is 1.000.000 bytes which is ~1MB. You can set higher values if you need to send bigger files through your webservice.
Check that and please let me know if it works.
EDIT: I recently found out that this is not the only setting you should make. You should also set the "maxRequestLength" attribute of the httpruntime node in web.config file, like:
<system.web>
<httpRuntime targetFramework="4.5" maxRequestLength="10000" executionTimeout="10800" />
</system.web>
Here, maxRequestLength is in KBs, so 10000 means ~10MBs (9,77MB exactly). If users have low bandwidths and your requestlength requirement is bigger than 10MB, then you can set executionTimeout attribute to a higher value. That is in seconds, so 10800 means 3 hours.
I think you got the picture here.
Cheers!
Related
from my Xamarin.Forms app I'm sending a picture and other fields to the server using HttpClient in Json format.
If I send a little picture I've got with my front camera it's working fine, if I send a larger picture I've got with the rear camera it doesn't work and I always get an exception: "Excepional error".
I tried to create the same code in a windows form application and it's working fine also with large images, but not from my App.
I have already modified on the server web.config to increase json content size:
<jsonSerialization maxJsonLength="50000000"/>
Can someone help ?! Thanks!!
This is the code on my app:
public async static Task<MyAppDataModels.Common.WsResponse> PostPhotoFromUser(int catalogItemId, int objReferenceId, int languageId, byte[] fileContent)
{
MyAppDataModels.Common.WsResponse MyResponse = new MyAppDataModels.Common.WsResponse();
try
{
HttpClient MyHttpClient = new HttpClient();
MyHttpClient.Timeout = TimeSpan.FromSeconds(520);
MyHttpClient.BaseAddress = new Uri(string.Format("{0}/Application/ApplicationPostPhotoFromUser", MyAppSettings.ServerApiUrl));
MyHttpClient.DefaultRequestHeaders.Accept.Clear();
MyHttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
MyHttpClient.DefaultRequestHeaders.AcceptCharset.Clear();
MyHttpClient.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
HttpRequestMessage MyWsRequest = new HttpRequestMessage(HttpMethod.Post, MyHttpClient.BaseAddress);
dynamic MyObjData = new JObject();
MyObjData["CatalogItemId"] = catalogItemId;
MyObjData["ObjReferenceId"] = objReferenceId;
MyObjData["UserId"] = string.Empty;
MyObjData["LanguageId"] = languageId;
MyObjData["Picture"] = fileContent;
string MySerializedPostedData = JsonConvert.SerializeObject(MyObjData);
MyWsRequest.Content = new StringContent(MySerializedPostedData, Encoding.UTF8, "application/json");
HttpResponseMessage MyWsResponse = await MyHttpClient.SendAsync(MyWsRequest, HttpCompletionOption.ResponseHeadersRead);
MyWsResponse.EnsureSuccessStatusCode();
var MyContentResponse = await MyWsResponse.Content.ReadAsStringAsync();
MyResponse.ResponseId = MyAppConstants.Constants.ResponseCode.Successfull;
}
catch (Exception ex)
{
MyResponse.ResponseId = MyAppConstants.Constants.ResponseCode.ErrorWhileProcessingRequest;
MyResponse.ResponseErrorMessage = ex.Message;
}
return MyResponse;
}
From the stacktrace,
System.Net.WebExceptionStatus.ProtocolError
means that the server responded with some 40x error, maybe 401 (Acess Denied) or something similar.
you can wrap your call in a:
try
{
}
catch(WebException ex){
}
then check the exceptions Status and cast the exception's response like that:
((HttpWebResponse)e.Response).StatusDescription
to get more info about what has gone wrong on the server.
EDIT:
Because you're uploading large files, you can resolve the "maximum request length exceeded exception", you need to modify your server's (ASP.NET for example) web.config file to accept large request size:
<configuration>
<system.web>
<httpRuntime maxRequestLength="50000" />
</system.web>
</configuration>
I am generating a small Json file which i wan't the user to download. So i want the browser to prompt the user to download the file.
I've tried many of answers suggested in related questions but those won't work for me.
The request is made by a click on an actionlink:
#Ajax.ActionLink("Generate JSON", "GenerateOcJson", new AjaxOptions { HttpMethod = "POST" })
i've tried:
var cd = new System.Net.Mime.ContentDisposition { FileName = fileName, Inline = false };
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(Encoding.UTF8.GetBytes(jsonString),
"application/json",
string.Format(fileName));
and:
Response.Clear();
Response.ContentType = "application/json";
Response.AppendHeader("Content-Disposition", "attachment; filename=foo.json");
Response.Write(jsonString);
Response.End();
But the browser won't download the file. I'm using MVC3 and this method is called by an actionlink. I've tried POST and GET requests.
If I inspect the request with Chrome i see the correct json had been written to the browser response.
Any clues? Thnx in advance
Try something like this (set mime type to plain text) and a normal #Html.ActionLink:
public ActionResult GenerateOcJson()
{
var document = new { Data = jsonString, ContentType = "text/plain", FileName = String.Format("JSONResults_{0}.json", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss")) };//... get from service layer
var cd = new System.Net.Mime.ContentDisposition
{
FileName = document.FileName,
// Inline = false means always prompt the user for downloading.
// Set it to true if you want the browser to try to show the file inline (fallback is download prompt)
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(document.Data, document.ContentType);
}
Just return a file result with the Application/Octet mediatype. No need to write the content-disposition header.
return File(Encoding.UTF8.GetBytes(jsonString),
System.Net.Mime.MediaTypeNames.Application.Octet,
fileName);
Use the generic mimetype of application/octet-stream. The browser will then treat the data as a file to download locally.
I have a script in which on Click on link i need to download PDF file present in temp folder on server and this i am doing it by calling AJAX function. that AJAX function is calling struts 2 action method which is reading content of the file and write it to output stream.
and now problem is if that file is not present in temp folder. that is throwing exception. so i decided to handle it by using json. if that file exist in temp folder. i am mapping the key to
jsonObject.put("exist", true)
and if that file does not exist in temp folder. i am mapping the key to
jsonObject.put("exist", false)
and in struts.xml i am handling the action by with this way
<action name="DisplayStaticPdf"
class="com.ui.DisplayStaticPdfAction">
<result name="success" type="json"/>
</action>
and in script i am handling it through this way
function downloadDoc(actionName){
$.ajax({
url: actionName,
type: 'post',
dataType: 'json',
error: function(data) {
if(data.exist!= null && data.exist == 'false'){
alert('The document you are trying to download does not exist at location. Please make sure file exist .');
}
},
success: function() {
}
});
}
and when file is not present, it is showing me the same alert. but when file is not present, it does nothing and does not download the pdf present in temp folder.
my action class looks like ->
String pdfFileName = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
String rawFileName = "abc.pdf";
String returnString = "fileNotExist";
jsonObject = new JSONObject();
ServletOutputStream out = response.getOutputStream();
response.setContentType("application/pdf");
URL url = new URL(fileURL);
URLConnection conn = url.openConnection();
if (conn.getContentLength() != 0 && conn.getContentLength() != -1)
{
bis = new BufferedInputStream(conn.getInputStream());
bos = new BufferedOutputStream(out);
try
{
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length)))
{
bos.write(buff, 0, bytesRead);
}
jsonObject.put("exist", true);
}
returnString = SUCCESS;
}
else
{
jsonObject.put("exist", false);
returnString ="fileNotExist";
}
return returnString;
hope you guys understand my issue. Anybody please put light on this whether i am doing it in right approach. or is there is any other easy way to do it
Thanks,
Ankit
I am trying to save attachments in ravenDb. I am getting a file not found error.
MVC View:
<input type="file" name="file" id="Ids2" style="float:right"/>
Over an ajax call, I am passing the value of the file name selected in the above control to the controller method - which in turns sends the file name to a custom method called "Upload"
public virtual string Upload(string fileName)
{
IDocumentSession session = GetCurrentDocumentSession();
var id = "upload/" + randomGen();
session.Advanced.DatabaseCommands.PutAttachment(id,null,
File.ReadAllBytes(fileName), optionalMetaData);
return id;
}
I am getting C:\ProgramFiles (x86)....does not have the file specified.
Lets say in the view - I browsed to C:/Doc1.txt and clicked on Add button that saves bunch of other fields on the view and also picks up the file name/path from the file upload control.
I get an error at session.advance.databasecommands... line
Could not find file 'C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\Doc1.txt'.
If I manually move the Doc1.txt file to the above location, ravenDB saves the attachment and I can see it from localhost:8080/static/upload/keyvalue
How can I make ravenDB take the file from the location the user selects and not from the what it looks like a default location of c:programfiles.....
EDIT:
function () {
var iFile = iContainer.find( '#Ids2' ).val();
var DataToSave = {
'Attachment' : iFile
};
var encodedData = $.toJSON(DataToSave);
$.ajax({
type: 'POST' ,
url: '/AttController/Attach' ,
data: encodedData,
contentType: 'application/json; charset=utf-8' ,
success: function (rc) {
if (rc.Success) {
// more javascript reroutes..business logic
}
else {
alert(rc.Message);
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert( 'Error attaching \n' + xhr.response);
}
});
};
Depending on the browser The html file control does not store the full path to the file. If you use Chrome and debug the script
var iFile = iContainer.find( '#Ids2' ).val();
Will return something like C:\fakepath\yourfile.txt. where as with IE the full path is returned.
Also you in your Ajax you are not pushing the bytes of the file but only the filename which means unless you are going to only ever run this website in a browser on the webserver the chances of the file being in the same place as the webserver is slim.
If you are trying to upload a file via ajax to a MVC controller I would suggest uploadify.
$("#Ids2").uploadify(
{
uploader: '/AttController/Attach',
swf: 'your/path/to/uploadify.swf',
cancelImg: 'your/path/to/cancel.jpg',
buttonText: 'Select File',
fileSizeLimit: '300KB',
fileTypeDesc: 'Image Files',
fileTypeExts: '*.gif; *.jpg; *.png',
auto: 'true',
multiple: 'false',
onError: function(type, info) {
},
onUploadSuccess: function(file, data, response) {
}
});
Then just change your controller action to
public virtual ActionResult Upload(HttpPostedFileBase FileData)
The FileData would have things like the FileName and would also have the file in an input stream.
I have a simple HTML file which includes jqGrid plugin. I am using jqGrid plugin to have a tree grid in my HTML page.
Now, I am trying to host this HTML file in node.js server. My server.js looks like this
var http = require('http');
var fs = require('fs');
var path = require('path');
http.createServer(function (request, response) {
console.log('request starting...');
var filePath = '.' + request.url;
console.log('filePath : '+filePath);
if (filePath == './')
filePath = './tree.html';
var extname = path.extname(filePath);
console.log('extname : '+extname);
var contentType = 'text/html';
switch (extname) {
case '.js':
contentType = 'text/javascript';
break;
case '.css':
contentType = 'text/css';
break;
}
path.exists(filePath, function(exists) {
if (exists) {
fs.readFile(filePath, function(error, content) {
if (error) {
response.writeHead(500);
response.end();
} else {
response.writeHead(200, { 'Content-Type': contentType });
response.end(content, 'utf-8');
}
});
} else {
response.writeHead(404);
response.end();
}
});
}).listen(8125);
So far, I am able to display my HTML content in browser [http://localhost:8125/]
Part of my HTML(tree.html) file looks like this
jQuery("#treegrid").jqGrid({
url: 'tree.json',
datatype: 'json',
//mtype: 'GET',
colNames: [/* "ID", */"Col 1", "Col 2",.. ],
colModel: [/* {
name: 'id',
index: 'id',
width: 1,
hidden: true,
key: true
}, */{ ...
If you can notice, I have specified 'tree.json' as URL attribute to load the tree grid. That is just reading a static file to load the tree grid with sample data.
Problem : Now, when I try to access my HTML file using [http://localhost:8125/]
I get an 404 Not Found error for [http://localhost:8125/tree.json]
Quick Solution : I can specify the relative path of the file 'tree.json' and it works.
Both my HTML file tree.html and tree.json are in the same directory (/tree) and I start my node.js server from command prompt (terminal) like this
tree> node server.js
I would like to know where I can place my tree.json in order to make my HTML work as intended.
Please feel free to ask any clarification.
Thanks in advance
You use the line
var filePath = '.' + request.url;
in your code which seems a little strange. Probably in case of request of 'tree.json' you will have .tree.json as the value of filePath instead of ./tree.json which you probably want to have. I think you should fix the code here.
Moreover it would be good to set 'application/json' as the value of contentType variable in case of .json extension in the same way like you set 'text/javascript' and 'text/css' for '.js' and '.css' files.