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);
}
Related
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).
I have an CSV file in memory that I want to upload to a Web API.
If I save the CSV file to disk and upload it, it gets accepted.
However, I want to avoid the extra work and also make the code cleaner by simply uploading the text I have as a MemoryStream Object (I think that's the correct format?).
The following code works for uploading the file:
string webServiceUrl = "XXX";
string filePath = #"C:\test.csv";
string cred = "YYY";
using (var client = new WebClient()){
client.Headers.Add("Authorization", "Basic " + cred);
byte[] rawResponse = client.UploadFile(webServiceUrl, "POST", filePath);
Console.WriteLine(System.Text.Encoding.ASCII.GetString(rawResponse));
}
How would I do if I had a string with all the contents and I want to upload it in the same way without having to save it down to a file?
WebClient.UploadData or WebClient.UploadString perhaps?
Thank you
EDIT:
I tried what you said but by using a local file (in case there was something wrong with the string), but I get the same error.
Here is what I suppose the code would be using your solution
string webServiceUrl = "XXX";
string file = #"C:\test.csv";
string cred = "YYY";
FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read);
BinaryReader r = new BinaryReader(fs);
byte[] postArray = r.ReadBytes((int)fs.Length);
using (var client = new WebClient())
{
client.Headers.Add("Authorization", "Basic " + cred);
using (var postStream = client.OpenWrite(webServiceUrl, "POST"))
{
postStream.Write(postArray, 0, postArray.Length);
}
}
Any thoughts?
Use OpenWrite() from the WebClient.
using (var postStream = client.OpenWrite(endpointUrl))
{
postStream.Write(memStreamContent, 0, memStream.Length);
}
As documentation mentioned:
The OpenWrite method returns a writable stream that is used to send data to a resource.
Update
Try to set the position of the MemoryStream to 0 before uploading.
memoryStream.Position = 0;
When you copy the file into the MemoryStream, the pointer is moved to the end of the stream, so when you then try to read it, you're getting a null byte instead of your stream data.
MSDN - CopyTo()
Copying begins at the current position in the current stream, and does not reset the position of the destination stream after the copy operation is complete.
I finally managed to solve it.
First I made a request using CURL that worked.
I analyzed the packet data and made an except copy of the packet.
I did a lot of changes, however, the final change was that using the different functions I found online it never closed the packet with a "Last-Boundary" while CURL did.
So by modifying the function, making sure it properly wrote a Last-Boundary it finally worked.
Also, another crucial thing was to set PreAuthenticate to true, the examples online didn't do that.
So, all in all:
1. Make sure that the packet is properly constructed.
2. Make sure you pre authenticate if you need to authenticate.
webrequest.PreAuthenticate = true;
webrequest.Headers[HttpRequestHeader.Authorization] = string.Format("Basic {0}", cred);
Don't forget to add SSL if using a https (which you probably do if you authenticate):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
Hope this helps someone.
And thanks for the help earlier!
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;
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.
I am writing an webscraper, to do the download content from a website.
Traversing to the website/URL, triggers the creation of a temporary URL. This new URL has a zipped text file. This zipped file has to be downloaded and parsed.
I have written a scraper in C# using WebClient and its function DownloadFileAsync(). The zipped file is read from the designated location on a trapped DownloadFileCompleted event.
My issue is The Windows Open/Save dialog are triggered. This requires user input and the automation is disrupted.
Can you suggest a way to bypass the issue ? I am cool with rewriting the code using any alternate libraries. :)
Thanks for reading
You can use 'HttpWebRequest' to perform the request and save the streamed bytes to disk.
var request = WebRequest.Create(#"your url here");
request.Method=WebRequestMethods.Http.Get;
var response = request.GetResponse();
using (var writeStream = new FileStream(#"path", FileMode.Create))
{
using (var readStream = response.GetResponseStream())
{
var buffer = new byte[1024];
var readCount = readStream.Read(buffer,0,buffer.Length);
while (readCount > 0)
{
writeStream.Write(buffer,0,buffer.Length);
readCount= readStream.Read(buffer,0,buffer.Length);
}
}
}