Download a PDF from a third party using ASP.NET HttpWebRequest/HttpWebResponse - c#

I want to send a url as query string e.g.
localhost/abc.aspx?url=http:/ /www.site.com/report.pdf
and detect if the above URL returns the PDF file. If it will return PDF then it gets saved automatically otherwise it gives error.
There are some pages that uses Handler to fetch the files so in that case also I want to detect and download the same.
localhost/abc.aspx?url=http:/ /www.site.com/page.aspx?fileId=223344
The above may return a pdf file.
What is best way to capture this?
Thanks

You can download a PDF like this
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri);
HttpWebResponse response = req.GetResponse();
//check the filetype returned
string contentType = response.ContentType;
if(contentType!=null)
{
splitString = contentType.Split(';');
fileType = splitString[0];
}
//see if its PDF
if(fileType!=null && fileType=="application/pdf"){
Stream stream = response.GetResponseStream();
//save it
using(FileStream fileStream = File.Create(fileFullPath)){
// Initialize the bytes array with the stream length and then fill it with data
byte[] bytesInStream = new byte[stream.Length];
stream.Read(bytesInStream, 0, bytesInStream.Length);
// Use write method to write to the file specified above
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}
}
response.Close();
The fact that it may come from an .aspx handler doesn't actually matter, it's the mime returned in the server response that is used.
If you are getting a generic mime type, like application/octet-stream then you must use a more heuristical approach.
Assuming you cannot simply use the file extension (eg for .aspx), then you can copy the file to a MemoryStream first (see How to get a MemoryStream from a Stream in .NET?). Once you have a memory stream of the file, you can take a 'cheeky' peek at it (I say cheeky because it's not the correct way to parse a PDF file)
I'm not an expert on PDF format, but I believe reading the first 5 chars with an ASCII reader will yield "%PDF-", so you can identify that with
bool isPDF;
using( StreamReader srAsciiFromStream = new StreamReader(memoryStream,
System.Text.Encoding.ASCII)){
isPDF = srAsciiFromStream.ReadLine().StartsWith("%PDF-");
}
//set the memory stream back to the start so you can save the file
memoryStream.Position = 0;

Related

Convert docx stream to pdf directly

I need to convert any file coming from web response into .pdf format, I'm currently getting it word docx file format from the URL and saving it into memory stream so i can later insert it in it's designated library.
The problem I'm facing now is that I'm saving my docx files directly into .pdf by putting an extension at the end which obviously ends up not opening the file later, So i'm trying to convert my memory stream into pdf directly .
Here is my piece of code that i tried to convert the the stream to .pdf but it looks like the file isn't getting converted correctly.
private Stream DownloadFromUrl(string url)
{
var webRequest = WebRequest.Create(url);
webRequest.Credentials = CredentialCache.DefaultNetworkCredentials;
webRequest.PreAuthenticate = true;
webRequest.UseDefaultCredentials = true;
//EventLogUtility.LogInformationMessage(DocumentURL);
string message = string.Empty;
using (Stream outputStream = new MemoryStream())
{
using (var response = webRequest.GetResponse())
{
using (var content = response.GetResponseStream())
{
var memory = new MemoryStream();
content.CopyTo(memory);
Document doc = new Document(memory);
doc.Save(memory, SaveFormat.Pdf);
return memory;
}
}
}
}
If the content in the stream is actually in the Microsoft Word file format (and not just plain text), then you need to map the format to the file format for PDF. I know there is a 'Print to PDF' function available in Word, you could try looking into that.

xlsx excel cannot open the file because the file format or file extension is not valid - c#

I am trying to create an excel file from the response of SSRS reporting server, on front-end I successfully able to download an excel file but when I open it I get the error.
xlsx excel cannot open the file because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.
Here is the code:
HttpWebRequest req =
(HttpWebRequest)WebRequest.Create(sTargetURL);
req.PreAuthenticate = true;
req.Credentials = new System.Net.NetworkCredential(strReportUser, strReportUserPW, strReportUserDomain);
HttpWebResponse HttpWResp = (HttpWebResponse)req.GetResponse();
Stream fStream = HttpWResp.GetResponseStream();
//Now turn around and send this as the response..
byte[] fileBytes = ReadFully(fStream);
string fileToAttach = Convert.ToBase64String(fileBytes);
HttpWResp.Close();
Stream stream = new MemoryStream(fileBytes);
result.Content = fileToAttach;
result.ContentType = "application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet";
result.FileName = fileName + ".xlsx";
result.result = true;
return result;
Any help would be appreciated.
Assuming response is some kind of HTTP response object that eventually gets sent to the browser, and that you have the actual Excel file contents in fStream, the problem is you are sending the Base64'd version of the file as the contents (which Excel is not going to understand):
Stream fStream = HttpWResp.GetResponseStream();
byte[] fileBytes = ReadFully(fStream);
string fileToAttach = Convert.ToBase64String(fileBytes);
result.Content = fileToAttach;
Since I can't see what response is, all I can say is you need to leave the file contents intact.
If you want to send the raw bytes, you could do:
Stream fStream = HttpWResp.GetResponseStream();
byte[] fileBytes = ReadFully(fStream);
result.Content = fileBytes;
If your response can handle a Stream, that would be the ideal way (then you don't have to convert it back and forth between a stream and byte data).
If result.Content has to be a string, then you have to worry about which encoding to use, and it'll look something like:
Stream fStream = HttpWResp.GetResponseStream();
byte[] fileBytes = ReadFully(fStream);
result.Content = Encoding.UTF8.GetString(fileBytes);
It wouldn't surprise me if Excel needs to be encoded as UTF-16 (Microsoft uses it quite heavily internally).

Send XML file on request

I'm trying to send a XML file on request, but I'm getting an error when I'm trying to copy the stream, which I'm loading the file into, to the output stream.
Right now it's working fine if I'm making the request (I use HttpListener btw) from a browser; it shows me my .xml just fine. But I'd also like to be able to download the .xml when I make the request.
Any suggestions?
string xString = #"C:\Src\Capabilities.xml";
XDocument capabilities = XDocument.Load(xString);
Stream stream = response.OutputStream;
response.ContentType = "text/xml";
capabilities.Save(stream);
CopyStream(stream, response.OutputStream);
stream.Close();
public static void CopyStream(Stream input, Stream output)
{
input.CopyTo(output);
}
The error I'm getting is at input.CopyTo(output); : "Stream does not support reading."
You probably get the error because the stream input actually is the response.OutputStream, which is an output stream and also makes the source and target of the copy operation the same stream - huh?
Essentially what your code does now (and this is wrong): You save the XML content to the response's output stream (which essentially already sends it to the browser). Then you try to copy the output stream into the output stream. This doesn't work and even if it did - why? You already wrote to the output stream.
You can simplify all this greatly in my opinion as follows:
// Read the XML text into a variable - why use XDocument at all?
string xString = #"C:\Src\Capabilities.xml";
string xmlText = File.ReadAllText(xString);
// Create an UTF8 byte buffer from it (assuming UTF8 is the desired encoding)
byte[] xmlBuffer = Encoding.UTF8.GetBytes(xmlText);
// Write the UTF8 byte buffer to the response stream
Stream stream = response.OutputStream;
response.ContentType = "text/xml";
response.ContentEncoding = Encoding.UTF8;
stream.Write(xmlBuffer, 0, xmlBuffer.Length);
// Done
stream.Close();

Getting Json Output from Byte Array

I just started a new project on WCF and to be honest I'm very new at this with limited knowledge.
So what I'm trying to do is open a file that is stored in my computer (e.g. word, pdf, etc.) and display the contents in the webpage in JSon format. I converted the file in a byte array and tried to display the Stream. When I did that it asked me to open the file or save it. I don't want that - I just want the contents of the file to be displayed on my local host when i call the method.
Here's what I have:
public string GetRawFile()
{
string file = #"C:\.....\TestFile.pdf";
byte[] rawFile = File.ReadAllBytes(file);
//Stream stream = new MemoryStream(rawFile);
//DataContractJsonSerializer obj = newDataContractJsonSerializer(typeof(string));
//string result = obj.ReadObject(stream).ToString();
//Deserializing
MemoryStream stream = new MemoryStream();
BinaryFormatter binForm = new BinaryFormatter();
stream.Write(rawFile, 0, rawFile.Length);
stream.Seek(0, SeekOrigin.Begin);
Object obj = (Object) binForm.Deserialize(stream);
System.Web.Script.Serialization.JavaScriptSerializer xyz = new System.Web.Script.Serialization.JavaScriptSerializer();
string ejson = xyz.Serialize(obj);
WebOperationContext.Current.OutgoingRequest.ContentType = "text/json";
return ejson;
}
I'm trying to return a string and it's not working, but when I return just the stream it's popping up the "openwith" message.
Also should I use the GET or POST on my datacontract. I'm using REST in C#.
I'm assuming that your file actually contains json. If that is the case just do this;
string file = File.ReadAllText("C:\path\to\file.extension");
You're making the problem a lot more complicated than it needs to be. Just read the file and return it's data as a string. I think you want to use GET for the http method. Generally speaking, you all use post if you're adding new content. If for example the users request would cause the application to write some data to a file or data base then you would typically use POST for the http method. If they're just requesting data, you almost always use GET.

FileStream with querystring in filename?

I have a need to be able to open a file on disk but pass in parameters to that file via a querystring. It's a .SWF file, so I'm passing in the parameter necessary to get it to load correctly.
The code I'm using to do so is:
FileStream fs = new FileStream(#"C:\test\file.swf?key=value", FileMode.Open, FileAccess.Read);
I'm getting an error opening the file: "Invalid characters in path" because of the "?" in the filename. Is there any way to load a file from disk into a FileStream object using a querystring in the filename?
I think you can't do what you're trying to do. When you load a file from disk the querystring does not exist as a concept. It will only return the bytes contained in the SWF file.
The querystring matters at the execution level.
So I solved this problem by putting my two SWF files on a web server and using the following code. Not exactly production ready code, but it illustrates the concept.
private static FileStream GetFileStream()
{
string url = #"http://www.someurl.com/shell.swf?Filename=actualfile.swf";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
WebResponse response = request.GetResponse();
byte[] result = null;
int byteCount = Convert.ToInt32(response.ContentLength);
using (BinaryReader reader = new BinaryReader(response.GetResponseStream()))
result = reader.ReadBytes(byteCount);
return new FileStream(result);
}

Categories