Return PDF from server - asp.net-mvc-3

My situation is as follows:
I am reading and returning a PDF file from the server, which is then displayed within an iframe. The following code works fine with IE. However, when I access the site via Chrome, I get all junk characters.
while ((byteCount = inStr.Read(buffer, 0, buffer.Length)) > 0)
{
if (HttpContext.Response.IsClientConnected)
{
HttpContext.Response.BufferOutput = true;
HttpContext.Response.ContentType = "application/pdf";
HttpContext.Response.OutputStream.Write(buffer, 0, buffer.Length);
//HttpContext.Response.Flush();
}
}
When I flush the response, I do get to see the PDF correctly. The problem is that calling flush is resulting in "Server cannot set status after HTTP headers have been sent" warning on the server.
Question is: Why is flush needed for Chrome and if there is a way to avoid flush? So far, I have read all the posts and unable to resolve the server error associated with flushing.
Server - IIS7, Windows Server 2008 R2
App - ASP.Net 4.0.30319.0, C#, Ajax

I hope this will help you, change your controller to return FileResult
public FileResult DownloadPDF()
{
buffer = <bytes from your PDF file>;
return File(buffer, "application/pdf", "download.pdf");
}
Show PDF
public FileResult ShowPDF()
{
buffer = <bytes from your PDF file>;
return File(buffer, "application/pdf");
}

Related

Edge file download error Couldn't download - Something went wrong

My web page has a link
href="https://...myapi.../files/get-user-role-file?fileID=etc..." target="_blank"
The web api call (get-user-role-file) returns a file with a mime type and a content disposition of inline.
the code returns a HttpResponseMessage. here is some of the code
ByteArrayContent content = new ByteArrayContent(_bytes);
string dispositionType = "inline";
if (_mimetype.IndexOf("octet-stream") > 0) dispositionType = "attachment";
ContentDispositionHeaderValue contentDisposition = new ContentDispositionHeaderValue(dispositionType) {
FileName = _filename
};
MediaTypeHeaderValue contentType = new MediaTypeHeaderValue(_mimetype);
response.Content = content;
response.Content.Headers.ContentDisposition = contentDisposition;
response.Content.Headers.ContentLength = _bytes.Length;
response.Content.Headers.ContentType = contentType;
This works in chrome and safari and firefox. In Edge it works for me in VS debug or in InPrivate mode or when run locally from my machine in IIS. It also works if the file type is one that can be opened in the browser OR if I have Fiddler running. BUT it does not work, for example, with a Excel doc in Edge run normally off of the web server. It does work for everyone else I have asked so far.
I have tried updating Edge and clearing all history.
What happens is a new tab is opened with the file URL and the downloads modal opens with a file named get-user-role-file.json and a message says "Couldn't download - Something went wrong...". In the network tab of the dev tools the call returns OK 200 and no error but also no response (Failed to load response data: No resource with given identifier found).
It's a mystery.

Client-Side error when uploading image on server ASP.NET Core

I am struggling with uploading an image from thew client-side to a folder on the server-side in .Net Core.I used Postman to check if the method on the server-side is working and it does without any problem,but when I try to upload an image from the client-side,I get an error on the server-side of type NullReferenceException:Object reference not set to an instance of an object.This is the Post method on the server-side:
[HttpPost]
public async Task Post(IFormFile file)
{
if (string.IsNullOrWhiteSpace(_environment.WebRootPath))
{
_environment.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
}
var uploads = Path.Combine(_environment.WebRootPath, "uploads");
//var fileName = file.FileName.Split('\\').LastOrDefault().Split('/').LastOrDefault();
if (!Directory.Exists(uploads)) Directory.CreateDirectory(uploads);
if (file.Length > 0)
{
using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
}
}
Apparently the method is thrown where I check if the length of the file is bigger than 0.On the client-side I get error "500 internal server error" and I tried to check using the debugger where exactly the error is thrown but i can't find anything that could resemble an error of some sort.This is the API method for the client-side:
public async Task UploadPictureAsync(MediaFile image)
{
User user = new User();
string pictureUrl = "http://10.0.2.2:5000/api/UploadPicture";
HttpContent fileStreamContent = new StreamContent(image.GetStream());
// user.Picture=GetImageStreamAsBytes(image.GetStream());
fileStreamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") {FileName=Guid.NewGuid() + ".Png",Name="image"};
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
using (var client = new HttpClient(clientHandler))
{
using (var formData = new MultipartFormDataContent())
{
formData.Add(fileStreamContent);
var response = await client.PostAsync(pictureUrl, formData);
if(response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
}
}
}
}
The image is declared in the Model as byte array:
public byte[] Picture { get; set; }
Does someone understand why my POST method has this behavior since the server-side works perfectly but fails when I try to upload an image from the client-side?What I find weird though is that when i read the error and I look at the Content-Type it is "text/plain" instead of "form-data" and I have tried to set it at the MutipartFormDataContent like this:
formData.Headers.ContentType.MediaType = "multipart/form-data";
I also tried to set the MediaTypeHeaderValue on the client like this:
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/octet-stream"));
I still get the wrong content type.
I have also tried a different approach with Stream instead of MediaFile but without any luck as it did not even hit the break point in debugger mode for the response.Any help would be appreciated! :)
I have managed to find the answer finalllyyyyy!!!The problem was on the client-side as I suspected and guess what,it was all about the correct name.It turns out that since on the server side I have IFormFile file I had to change the client side to take the parameter name "file" instead of image as well so that it could work.Thank you #Jason for the suggestions as I didn't understand the error from the first place and did some debugging on the server-side to help me figure it out.

XMLHttpRequest object is empty after server response - what am I doing wrong?

This is my first post on stackoverflow, and it concerns a problem I'm having while trying to learn the basics of Ajax.
This is the scenario:
I have created an HTML file with an embedded script
The script ...
- creates an XMLHttpRequest object
- invokes open() to assign the HTTP method and URL
- assigns the event handler to the onreadystatechange
property
- sends the request
What is the request?
The request is simply going to the local web server (Apache) on the same host to run a php script. The php script creates an XML file, and populates the file with a single value, which is the time on the server.
What does the client do with the response?
The event handler uses DOM to extract the time value from the XML and inserts it as the innerHTML in a div element.
What's not working?
Actually it works fine in IE8, but I can't get it to work in Firefox!
What does work, and what doesn't?
The request is being sent, and the event handler is indeed being invoked, both in IE8 and in Firefox. Whereas IE8 populates the div on the web page beautifully, in Firefox the XMLHttpRequest object appears to be empty; that is to say, the readyState is being updated but there are no reponse headers or text, and no status or status text.
What I have done to investigate
- I have reviewed the MDN documentation for XMLHttpRequest to see whether I'm doing something wrong, but my code appears ok.
- I have populated the script with lots of alerts statements to try to debug this, but I can find only the symptoms, not the cause.
- I have downloaded and installed Fiddler to examine the request and responses: I can confirm that the requests are being sent from both IE8 and Firefox, and (not only that) that the web server is returning the EXACT same responses to both browsers - headers and body.
So the question is:
Why is this not working? Ajax is no longer a new technology and if it works ok in IE8 (6 years old) then surely Firefox 31 (1 year old) should have no problem.
Here is my server request code:
function getServerTime()
{
if (http)
{
var url;
var userAgent = window.navigator.userAgent
var msie = userAgent.indexOf("MSIE") >= 0;
var msieVerNum;
if (msie)
{
/* The string "MSIE" has been found so this script
* is running under Internet Explorer. */
//Remove the portion of the user agent string to the left of "MSIE ".
userAgent = userAgent.substring(userAgent.indexOf("MSIE "));
/* Remove "MSIE " from the user agent string thus leaving the
* version number at the start of the string. */
userAgent = userAgent.replace("MSIE ","");
msieVerNum = parseInt(userAgent);
if (msieVerNum <= 8)
{
/* This script is running under Internet Explorer 8 or older.
* Hence, using the Date.getTime() function.
*/
url = "http://localhost./telltimeXML.php?" + (new Date()).getTime();
}
}
if (! msie || msieVerNum >= 9)
{
if (Date.now)
{
url = "http://localhost./telltimeXML.php?" + Date.now();
}
}
if (typeof(url) != "undefined")
{
http.open("GET", url, true);
http.onreadystatechange = useHttpResponse;
//http.send(null);
http.send();
}
}
else
{
alert("no XMLHttpRequest object");
}
}
...and here is my event handler:
function useHttpResponse()
{
if (http.readyState == 4)
{
if (http.status == 200)
{
document.getElementById("ShowTime").innerHTML =
http.responseXML.getElementsByTagName("timenow")[0].childNodes[0].nodeValue;
}
}
else
{
document.getElementById("ShowTime").innerHTML = "<img src=\"0002.gif\" />";
}
}

HttpWebRequest.BeginGetResponse completes too late

I use in my code calls to HttpWebRequest.BeginGetResponse() method to get data from my server. The server produces content that may range from few KB to few GB.
My problem is that HttpWebRequest.BeginGetResponse completes too late. It should complete immediately after the connection to the server is established and the HTTP header is received.
Here is sample code using GET method:
public bool StartDownload()
{
try
{
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(m_getUrl);
myHttpWebRequest.Method = "GET";
// Start the asynchronous request.
m_requestState = new RequestState();
m_requestState.request = myHttpWebRequest;
myHttpWebRequest.BeginGetResponse(new AsyncCallback(ResponseCompleted), m_requestState);
}
catch (Exception)
{
m_requestState = null;
}
return m_requestState != null;
}
private void ResponseCompleted(IAsyncResult result)
{
RequestState myRequestState = (RequestState)result.AsyncState;
HttpWebRequest myHttpWebRequest = myRequestState.request;
m_logger.LogMessage("ResponseCompleted notification received!");
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)myHttpWebRequest.EndGetResponse(result);
}
catch (Exception)
{
}
.......
}
I run the code using "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.39.1.tar.bz2" for example and the result looks like:
hh:mm:ss.ms
12:51:30.9440000 - Download started!
12:53:04.8520000 - ResponseCompleted notification received!
12:53:04.8560000 - Header received!
12:53:04.8570000 - DataReceived: 524288 bytes
.........................................
12:53:04.8940000 - DataReceived: 78818 bytes
12:53:04.8940000 - Request data received!
12:53:04.8940000 - Received bytes: 76100578
The problem can be easily detected in the log. It is not possible to spend more that one minute to connect and 38 ms to download about 72.5 MB.
It seems that the data is downloaded somewhere on the phone and the RequestComplete notification is sent to the application only when the full content is available locally. This is not OK for me because I need to show progress for the operation.
I get the same result on the device and emulator for WP7 (also on WP7.1).
I run same code on Windows desktop and it run correctly: the request completes within one second and the rest of the download takes about 1-2 minutes.
Is there any solution on WP7 or WP 7.1?
The newly introduced WP 7.1 API "Background File Transfers" does not help because I need full control over the HTTP headers and content. Not all HTTP requests that I make to the server produce files as output.
Thank you!
Mihai
You need to disable response buffering if you want to stream the data down. You can do this by setting AllowReadStreamBuffering to false.
HttpWebRequest myHttpWebRequest = WebRequest.CreateHttp(m_getUrl);
myHttpWebRequest.Method = "GET";
myHttpWebRequest.AllowReadStreamBuffering = false;

MVC 3 ContentResult binary file with firefox strange issue

I've got an MVC 3 app that allows users to upload files with some data entry stuff. I've set up a controller that fetches those documents and buffers them out to the user like so
[OutputCache(Duration = 1200, VaryByParam = "id")]
public ContentResult GetNarrative(int id)
{
Response.Clear();
Response.BufferOutput = true;
Response.ContentType = "application/octet-stream";
var narrative = attachRepo.GetNarrative(id);
if (narrative == null || narrative.Narrative == null)
return null;
Response.AddHeader("Content-Disposition",
string.Format("attachment;filename={0}",
Server.UrlEncode(narrative.Filename)));
Response.OutputStream.Write(narrative.Narrative.ToArray(),
0, narrative.Narrative.ToArray().Length);
Response.OutputStream.Flush();
return Content("");
}
This works fine and well, the interesting thing is that when I have the output cache line, my firefox download dialog looks like this
However when I comment out the output cache line it looks like the expected dialog
This isn't really a blocking issue, as it works just fine in IE and Chrome just downloads by default, but I am curious why this would be happening and if anyone has experienced this and worked around it.
Thanks!
I've found that firefox ignores the filename in the Attachment. It tends to use he URL to set the filename.
Try putting at the end of the URL ?filename.docx
And see if it fixes things.

Resources