Howto: download a file keeping the original name in C#? - c#

I have files on a server that can be accessed from a URL formatted like this:
http:// address/Attachments.aspx?id=GUID
I have access to the GUID and need to be able to download multiple files to the same folder.
if you take that URL and throw it in a browser, you will download the file and it will have the original file name.
I want to replicate that behavior in C#. I have tried using the WebClient class's DownloadFile method, but with that you have to specify a new file name. And even worse, DownloadFile will overwrite an existing file. I know I could generate a unique name for every file, but i'd really like the original.
Is it possible to download a file preserving the original file name?
Update:
Using the fantastic answer below to use the WebReqest class I came up with the following which works perfectly:
public override void OnAttachmentSaved(string filePath)
{
var webClient = new WebClient();
//get file name
var request = WebRequest.Create(filePath);
var response = request.GetResponse();
var contentDisposition = response.Headers["Content-Disposition"];
const string contentFileNamePortion = "filename=";
var fileNameStartIndex = contentDisposition.IndexOf(contentFileNamePortion, StringComparison.InvariantCulture) + contentFileNamePortion.Length;
var originalFileNameLength = contentDisposition.Length - fileNameStartIndex;
var originalFileName = contentDisposition.Substring(fileNameStartIndex, originalFileNameLength);
//download file
webClient.UseDefaultCredentials = true;
webClient.DownloadFile(filePath, String.Format(#"C:\inetpub\Attachments Test\{0}", originalFileName));
}
Just had to do a little string manipulation to get the actual filename. I'm so excited. Thanks everyone!

As hinted in comments, the filename will be available in Content-Disposition header. Not sure about how to get its value when using WebClient, but it's fairly simple with WebRequest:
WebRequest request = WebRequest.Create("http://address/Attachments.aspx?id=GUID");
WebResponse response = request.GetResponse();
string originalFileName = response.Headers["Content-Disposition"];
Stream streamWithFileBody = response.GetResponseStream();

Related

Uploading a file like form-data in postman

I have found some answers here that give examples but none seems to work for me..
this is how my postman looks:
In the code I download the picture from a URL, save it as jpeg inside a folder and then I try to upload that image with a POST request, here is how it looks:
var fileName = image.PhotoId + ".jpeg";
await Task.WhenAll(client.DownloadFileTaskAsync(new Uri(image.ImageUrl), #"wwwroot\images\"+fileName));
var files = Directory.GetFiles(#"wwwroot\images\", "*.jpeg");
var filePath = Path.Combine(#"wwwroot\images\", fileName);
using var stream = File.OpenRead(filePath);
var file_content = new ByteArrayContent(new StreamContent(stream).ReadAsByteArrayAsync().Result);
var formData = new MultipartFormDataContent();
formData.Add(file_content, "file", fileName);
var res = await clientAsync.PostAsync(url, formData);
problem is the response that I get in the code is an error..:
{"error_code":6,"error_message":"Sorry, please try a different picture"}
this type of response is the same one I get when trying to upload a pdf instead of a jpeg on postman so I guess the file is getting corrupted in the code somewhere.
would love to get any ideas to where the problem is!

Delay before starting download of pdf file using DownloadFile C#

I am attempting to download a large 25 megabyte pdf file using the following code:
string url = "http://aaa.aaa/test.pdf";
string clientfile = HttpContext.Current.Server.MapPath("~/123.pdf");
WebClient wc = new WebClient();
wc.DownloadFile(new Uri(url, UriKind.Absolute), clientfile);
However the file signature is corrupted and does not download correctly. Is there a way to delay the file download before the download actually starts?
I know the file is correct since if I download it from a browser, the file is not corrupted.
Thanks
I found the problem. When downloading a pdf file, it is actually zipped in a format called "GZIP". When using a browser, the file is automatically unzipped for the client. When using the WebClient DownloadFile method in .NET, it must be done manually. First create a class to derive the WebClient class as follows:
public class GzipWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
return request;
}
}
Then change your code to use the above class:
string url = "http://aaa.aaa/test.pdf";
string clientfile = HttpContext.Current.Server.MapPath("~/123.pdf");
GzipWebClient wc = new GzipWebClient();
wc.DownloadFile(new Uri(url, UriKind.Absolute), clientfile);
The pdf file will now be correctly downloaded and unzipped automatically.

Copy file from the obtained path to a domain

Hi all is it possible to copy a file from the path obtained to the domain, I tried as follows but I am getting an exception as uri formats are not supported.. So can some one help me how to copy the file
string filePath = "D:\\Folder\\filename.jpg";
FileInfo fileInfo = new FileInfo(filePath);
if (fileInfo.Exists)
{
path = "http://WWW.somedomain.com";
string temppath = path + "/Temp" + "/" + fileInfo.Name;
if (!File.Exists(temppath))
{
var uri = new Uri(temppath);
File.Copy(filePath, uri.AbsoluteUri);
}
You want to check the existence of file on the server. This is not possible using File.Exist method as it doesn't supports the URI. This method expect the relative path and checked the existence on machine (physical location).
In this case you should use WebRequest and get the response from the server. If server returns 404 then your file doesn't exist on the serve or you can check the Content Length.
WebRequest request = WebRequest.Create(new Uri(temppath));
request.Method = "HEAD";
WebResponse response = request.GetResponse()
var contentLength = response.ContentLength;
if (contentLength < 0)
{
// file doesn't exist.
}

URL Formats are not supported

I am reading File with File.OpenRead method, I am giving this path
http://localhost:10001/MyFiles/folder/abc.png
I have tried this as well but no luck
http://localhost:10001//MyFiles//abc.png
but its giving
URL Formats are not supported
When I give physical path of my Drive like this,It works fine
d:\MyFolder\MyProject\MyFiles\folder\abc.png
How can I give file path to an Http path?
this is my code
public FileStream GetFile(string filename)
{
FileStream file = File.OpenRead(filename);
return file;
}
Have a look at WebClient (MSDN docs), it has many utility methods for downloading data from the web.
If you want the resource as a Stream, try:
using(WebClient webClient = new WebClient())
{
using(Stream stream = webClient.OpenRead(uriString))
{
using( StreamReader sr = new StreamReader(stream) )
{
Console.WriteLine(sr.ReadToEnd());
}
}
}
You could either use a WebClient as suggested in other answers or fetch the relative path like this:
var url = "http://localhost:10001/MyFiles/folder/abc.png";
var uri = new Uri(url);
var path = Path.GetFileName(uri.AbsolutePath);
var file = GetFile(path);
// ...
In general you should get rid of the absolute URLs.
The best way to download the HTML is by using the WebClient class. You do this like:
private string GetWebsiteHtml(string url)
{
WebRequest request = WebRequest.Create(url);
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
string result = reader.ReadToEnd();
stream.Dispose();
reader.Dispose();
return result;
}
Then, If you want to further process the HTML to ex. extract images or links, you will want to use technique known as HTML scrapping.
It's currently best achieved by using the HTML Agility Pack.
Also, documentation on WebClient class: MSDN
Here I found this snippet. Might do exactly what you need:
using(WebClient client = new WebClient()) {
string s = client.DownloadFile(new Uri("http://.../abc.png"), filename);
}
It uses the WebClient class.
To convert a file:// URL to a UNC file name, you should use the Uri.LocalPath property, as documented.
In other words, you can do this:
public FileStream GetFile(string url)
{
var filename = new Uri(url).LocalPath;
FileStream file = File.OpenRead(filename);
return file;
}

No response when using WebClient.UploadFile

I'm uploading a file using the UploadFile method on the WebClient object. When the file is uploaded I would like to get a confirmation and according to MSDN (and also here on stackoverflow: Should I check the response of WebClient.UploadFile to know if the upload was successful?) I should be able to read the returned byte array but that is always empty.
Am I doing something the wrong way?
WebClient FtpClient = new WebClient();
FtpClient.Credentials = new NetworkCredential("test", "test");
byte[] responseArray = FtpClient.UploadFile("ftp://localhost/Sample.rpt", #"C:\Test\Sample.rpt");
string s = System.Text.Encoding.ASCII.GetString(responseArray);
Console.WriteLine(s); //Empty string
Or is it always successful if it doesn't return an exception?
Answer to myself: I couldn't make any sense of it so i switched to edt ftp (http://www.enterprisedt.com/) instead.

Categories

Resources