Downloading a file with RTL characters in the name, with C# WebRequest - c#

I am trying to download a file which has hebrew characters in the name
https://example.com/path/‏צילום מסך 2014‏.04‏.16 ב‏.16.44.30.png
When I try to download with the browser, the filename is correctly encoded and the server returns the file.
If I am downloading with C# code from the server, the filename is not encoded properly thus the server returns error 403.
If I encode the filename using HttpUtility.UrlEncode() and pass it to the WebRequest class, it is encoded properly but it has the same result (error 403).
I inspected the web calls with Fiddler and the encoded filename is different than what browser is encoding. If I get the filename and decode it, the filename is different (see below)
https://example.com/path/צילום מסך 2014.04.16 ב.16.44.30.png
I suspect that the problem is that the filename is partially encoded with Right-To-Left characters and the WebRequest class isn't equipped with the methods to handle it.
please see below the code used to download all of the files.
private byte[] GetFile(string url)
{
byte[] result;
byte[] buffer = new byte[4096];
WebRequest request = WebRequest.CreateHttp(url);
using (var remoteStream = request.GetResponse().GetResponseStream())
{
using (MemoryStream memoryStream = new MemoryStream())
{
int count = 0;
do
{
count = remoteStream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, count);
}
while (count != 0);
result = memoryStream.ToArray();
}
}
return result;
}

Related

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).

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

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;

How to get the ZIP file from Base64 string in Javascript?

I am trying to get the compressed ZIP file back in Javascript. I am able to convert the zip file into Base64 String format. (Zip file is in Server)
Here is my try (at Server Side)
System.IO.FileStream fs = new System.IO.FileStream(SourceFilePath + "Arc.zip", System.IO.FileMode.Open);
Byte[] zipAsBytes = new Byte[fs.Length];
fs.Read(zipAsBytes, 0, zipAsBytes.Length);
String base64String = System.Convert.ToBase64String(zipAsBytes, 0, zipAsBytes.Length);
fs.Close();
if (zipAsBytes.Length > 0)
{
_response.Status = "ZipFile";
_response.Result = base64String;
}
return _json.Serialize(_response);
This part of code returns the JSON data. This JSON data includes the Base64 string. Now what i want to do is to get the original zip file from Base64 string. I searched over the internet but not get the idea.
Is this achievable ?.
It is achievable. First you must convert the Base64 string to an Arraybuffer. Can be done with this function:
function base64ToBuffer(str){
str = window.atob(str); // creates a ASCII string
var buffer = new ArrayBuffer(str.length),
view = new Uint8Array(buffer);
for(var i = 0; i < str.length; i++){
view[i] = str.charCodeAt(i);
}
return buffer;
}
Then, using a library like JSZip, you can convert the ArrayBuffer to a Zip file and read its contents:
var buffer = base64ToBuffer(str);
var zip = new JSZip(buffer);
var fileContent = zip.file("someFileInZip.txt").asText();
JavaScript does not have that functionality.
Theoretically there can be some js library that does this, but it's size probably would be bigger than the original text file itself.
You can also enable gzip compression on your server, so that any output text gets compressed. Most of the browsers would then uncompress the data upon its arrival.

Disallowed key characters while uploading image in base64 format

I'm developing Windows phone(8.0)apps and I'm new to it,I'm using below code to post image to server in Base64 format using post client
Uri uri = new Uri(UPLOAD_IMAGE_PATH);
UploadImageData requestData = new UploadImageData();
requestData.image = base64String;
string jsonString = JsonConvert.SerializeObject(requestData);
PostClient proxy = new PostClient(jsonString);
proxy.DownloadStringCompleted += new PostClient.DownloadStringCompletedHandler(proxy_DownloadStringCompleted);
proxy.DownloadStringAsync(uri);
where base64String is my image string encoded in Bae64 by using below code
internal static string ImageToBase64String(Stream choosenPhoto,Image image)
{
WriteableBitmap bmp = new WriteableBitmap((BitmapSource)image.Source);
byte[] byteArray;
using (MemoryStream stream = new MemoryStream())
{
bmp.SaveJpeg(stream, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
byteArray = stream.ToArray();
return Convert.ToBase64String(byteArray);
}
}
In below response it returns "disallowed key charaters" on result.
void proxy_DownloadStringCompleted(object sender, WindowsPhonePostClient.DownloadStringCompletedEventArgs e)
{
string result = e.Result;
}
But when i post same JSON string using REST Client from Mozilla, JSON response from server is successfull.
I searched about this and i got some links link 1, link 2 that i need to allow characters on server side in Input.php file, So exactly what kind of character i need to allow. It works from REST Client did i miss something in my C# code, Please help me
It doesn't seem to explicitly mention the Base64 string (unless I'm missing something, having never developed for a WinPhone OS). Have you checked the URL that you're sending a POST request to?

C# save a file from a HTTP Response

Im trying to download and save a file from a HttpWebResponse but im having problems saving the file (other than Text Files) properly.
I think its something to do with this part:
byte[] byteArray = Encoding.UTF8.GetBytes(http.Response.Content);
MemoryStream stream = new MemoryStream(byteArray);
Text Files work fine with the above code but when I try to save the Content to an Image file it gets corrupted.
How do i write this 'string' data to an image file (and other binary files)
Forgot to mention, This is .NET CP 3.5 and I have a wrapper class around the HttpWebResponse class to add OAuth etc.
The problem is you're interpreting the binary data as text, even if it isn't - as soon as you start treating the content as a string instead of bytes, you're in trouble. You haven't given the details of your wrapper class, but I'm assuming your Content property is returning a string - you won't be able to use that. If your wrapper class doesn't let you get at the raw data from the web response, you'll need to modify it.
If you're using .NET 4, you can use the new CopyTo method:
using (Stream output = File.OpenWrite("file.dat"))
using (Stream input = http.Response.GetResponseStream())
{
input.CopyTo(output);
}
If you're not using .NET 4, you have to do the copying manually:
using (Stream output = File.OpenWrite("file.dat"))
using (Stream input = http.Response.GetResponseStream())
{
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
Use WebClient.DownloadFile. You can do it manually (something like this), but WebClient is the best bet for simple downloads.
Simplest way I found is:
Use ReadAsByteArrayAsync to get the data.
List item
File.WriteAllBytes to save the file.
No need to loop through anything. Example in context below:
[TestClass]
public class HttpTests
{
[TestMethod]
public void TestMethod1()
{
var jsObject = (dynamic)new JObject();
jsObject.html = "samplehtml.html";
jsObject.format = "jpeg";
const string url = "https://mywebservice.com/api";
var result = GetResponse(url, jsObject).GetAwaiter().GetResult();
File.WriteAllBytes($#"c:\temp\httpresult.{jsObject.format}", result);
}
static async Task<byte[]> GetResponse(string uri, dynamic jsObj)
{
var httpClient = new HttpClient();
var load = jsObj.ToString();
var content = new StringContent(load, Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync(uri, content);
return await response.Content.ReadAsByteArrayAsync();
}
}

Categories