Downloading a file from the website via the download link - c#

There's a code that downloads files by links (.exe), which actually needs a link to download the file, it can be a direct link or a link to the file that needs to be downloaded. In 80% of cases, everything works (https://ru.download.nvidia.com/GFE/GFEClient/3.25.1.27/GeForce_Experience_v3.25.1.27.exe (https://www.nvidia.com/en-gb/geforce/geforce-experience/)), but where you need to confirm the cookie (https://drivers.amd.com/drivers/installer/22.20/beta/amd-software-adrenalin-edition-22.8.2-minimalsetup-220825_web.exe (https://www.amd.com/en/support)), the download doesn't work
Maybe it can somehow work normally?
using var handler = new HttpClientHandler();
handler.AllowAutoRedirect = true;
handler.CookieContainer = new CookieContainer();
handler.UseCookies = true;
using var client = new HttpClient(handler);
SaveFile(client, fileUri, destinationFolder)
async Task SaveFile(HttpClient client, Uri uri, string destinationFolder)
{
using var response = await client.GetAsync(uri);
using var stream = await response.Content.ReadAsStreamAsync();
var name = Guid.NewGuid().ToString() + ".exe";
using var fs = new FileStream(Path.Combine(destinationFolder, name), FileMode.CreateNew);
await stream.CopyToAsync(fs);
}

Related

How to return PDF content from another HttpResponseMessage to the browser?

I am in the process of creating a proxy server that makes a request to a PDF Blob link then takes the request to setup its HttpResponse Header which we sent to the client. This diagram should explain
As of now, I am successful at making the request to get the pdf content however I am not sure how to send that back to the user. I have followed other Stackoverflow post such as this one : https://stackoverflow.com/a/43232581/10541061
I turn the response message in step 3 of the diagram to a stream and sent it back in the new HttpResponseMessage content.But instead of PDF content , I get a json file
What I want to return to the client
What I am actually returning to the client
Here is the code I am using to create this proxy endpoint
[AllowAnonymous]
[HttpGet("openPDF")]
public async Task<HttpResponseMessage> OpenPDF([FromQuery] string url)
{
var _httpClient = _httpClientFactory.CreateClient();
var response = await _httpClient.GetAsync(url);
var stream = await response.Content.ReadAsStreamAsync();
HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.OK);
message.Content = new StreamContent(stream);
message.Content.Headers.ContentLength = stream.Length;
message.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return message;
}
EDIT
Ok so this actually sends back the PDF when I write the proxy like this
[AllowAnonymous]
[HttpGet("openPDF")]
public async Task<FileStreamResult> OpenPDF([FromQuery] string url)
{
var fileStream = new MemoryStream();
var _httpClient = _httpClientFactory.CreateClient();
var file = await _httpClient.GetStreamAsync(url).ConfigureAwait(false);
await file.CopyToAsync(fileStream);
fileStream.Position = 0;
return File(fileStream, "application/pdf", "filename.pdf");
}
The problem is I want to update the content-disposition to inline so I can force this to open in the browser instead of downloading.So I decided to take the filestream and injecting that in the httpResponseMessage.content instead but that still didn't work. It would continue to send me a json file
[AllowAnonymous]
[HttpGet("openPDF")]
public async Task<HttpResponseMessage> OpenPDF([FromQuery] string url)
{
var fileStream = new MemoryStream();
var _httpClient = _httpClientFactory.CreateClient();
var file = await _httpClient.GetStreamAsync(url).ConfigureAwait(false);
await file.CopyToAsync(fileStream);
fileStream.Position = 0;
HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.OK);
message.Content = new StreamContent(fileStream);
message.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return message;
}
To be honest, I thought defining the content-type should suffice but guess not
This is pretty straight forward for .NET 6... suspect it should be roughly the same for .NET 4x... This uses the NuGet package Azure.Storage.Blobs
https://github.com/Azure/azure-sdk-for-net/blob/Azure.Storage.Blobs_12.13.1/sdk/storage/Azure.Storage.Blobs/README.md
[HttpGet("stream")]
public async Task GetBlobAsync()
{
var url = new Uri("https://path.to.blob.content/xxx");
var blobClient = new BlobClient(url);
Response.Headers.Add("Content-Type", "application/pdf");
Response.Headers.Add("Content-Disposition", #"attachment;filename=""intended file name.pdf""");
await blobClient.DownloadToAsync(Response.Body);
}
for .NET 4x.
try to add:
result.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("inline")
{
FileName = "filename.pdf"
};

I get wrong file when I download it by C# code

When I open this excel file link in my browser, It will be downloaded successfully.
But when I download it by the following c# code
private void downloadFile()
{
string remoteUri = "http://members.tsetmc.com/tsev2/excel/MarketWatchPlus.aspx?d=0";
string fileName = #"g:\temp.xlsx";
using (var client = new WebClient())
{
client.DownloadFile(remoteUri, fileName);
}
}
and I open it in the file explorer, I get the file format error:
What is wrong with my code?
Unzip file and write.
string remoteUri = "http://members.tsetmc.com/tsev2/excel/MarketWatchPlus.aspx?d=0";
string fileName = #"g:\temp.xlsx";
using (var client = new WebClient())
{
using var stream = client.OpenRead(remoteUri);
using var zipStream = new GZipStream(stream, CompressionMode.Decompress);
using var resultStream = new MemoryStream();
zipStream.CopyTo(resultStream);
File.WriteAllBytes(fileName, resultStream.ToArray());
}
If you look at the response headers provided by the remoteUri, you will notice that the particular endpoint is actually serving content in compressed format.
Content-Encoding: gzip
So the content you get back is not a direct excel file, rather a zip file. So for the piece of code to work, the file name should be temp.zip instead of temp.xlsx
private void downloadFile()
{
string remoteUri = "http://members.tsetmc.com/tsev2/excel/MarketWatchPlus.aspx?d=0";
string fileName = #"g:\temp.zip";
using (var client = new WebClient())
{
client.DownloadFile(remoteUri, fileName);
}
}
Having said that, inline is a better approach to download the file.
Create an instance of HttpClient by passing in a HttpClientHandler which has the AutomaticDecompression property set to DecompressionMethods.GZip to handle Gzip decompression automatically. Next read the data and save it to temp.xlsx file.
string remoteUri = "http://members.tsetmc.com/tsev2/excel/MarketWatchPlus.aspx?d=0";
string fileName = #"g:\temp.xlsx";
HttpClientHandler handler = new HttpClientHandler()
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
HttpClient client = new HttpClient(handler);
var response = await client.GetAsync(remoteUri);
var fileContent = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes(fileName, fileContent);

How to download a file on a ASP.Net page given a stream from a wcf service

I have a asp.net wep page where I make a POST call to a WCF REST service and it returns a stream of the file.
server code:
public Stream GetDocument() {
String headerInfo = "attachment; filename=" + FileName;
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.OK;
WebOperationContext.Current.OutgoingResponse.Headers["Content-Disposition"] = headerInfo;
WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream";
return new MemoryStream(rawDoc.ByteArray);
}
client code:
sendPost(Dictionary<string, string> msgDump)
{
var jsonContent = JsonConvert.SerializeObject(msgDump);
var buffer = System.Text.Encoding.UTF8.GetBytes(jsonContent);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await client.PostAsync("http://localhost:63301/DocumentService.svc/GetDocument", byteContent);
var contentStream = await response.Content.ReadAsStreamAsync();
}
I get the filestream but at this point I don't know how to get the browser to download the file for you. I am going to be hosting this on IIS so I don't want to do any sort of file.create to a specific path. After a lot of googling I cant come up with a solution. the code may seem off since I didn't copy all of it, but you should get the gist.
Thanks for the help!

Download the file from a certain point

I want to download file from URL (like video). I know how to do it using WebClient, but now I want to start download from some point of this file (for example from half) as far as I know it is impossible to do it using WebClient. So how can I do it?
This should work if server supports byte range
using (var httpClient = new HttpClient())
{
var bytesToSkip = 100_000;
var httpRequestMessage = new HttpRequestMessage
{
RequestUri = new Uri("file to download"),
Method = HttpMethod.Get,
Headers = { Range = new RangeHeaderValue(bytesToSkip, null)}
};
var response = await httpClient.SendAsync(httpRequestMessage);
var content = await response.Content.ReadAsByteArrayAsync();
}

Windows store get download progress

After struggling for a long time i finally got a code for downloading a file with using authentication and sending a header with a range in a windows store application , now the next level is to get a progress bar of the download , so any idea of the classes and methods that should be used for getting the download operation?
This is my code:
var httpClientHandler = new HttpClientHandler();
httpClientHandler.Credentials = new System.Net.NetworkCredential("", "");
var client = new HttpClient(httpClientHandler);
System.Net.Http.HttpRequestMessage request = new System.Net.Http.HttpRequestMessage(HttpMethod.Post, new Uri(""));
request.Headers.Range = new RangeHeaderValue(0,null);
HttpResponseMessage response = await client.SendAsync(request);
Stream stream = await response.Content.ReadAsStreamAsync();
StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.GenerateUniqueName);
await Windows.Storage.FileIO.WriteBytesAsync(file, ReadStream(stream));
This task will be easier if you switch from System.Net.Http.HttpClient to Windows.Web.Http.HttpClient.
using Windows.Web.Http;
using Windows.Web.Http.Filters;
private async void Foo(StorageFolder folder, string fileName)
{
Uri uri = new Uri("http://localhost");
var filter = new HttpBaseProtocolFilter();
filter.ServerCredential =
new Windows.Security.Credentials.PasswordCredential(uri.ToString(), "foo", "bar");
var client = new HttpClient(filter);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Headers.Add("Range", "bytes=0-");
// Hook up progress handler.
Progress<HttpProgress> progressCallback = new Progress<HttpProgress>(OnSendRequestProgress);
var tokenSource = new CancellationTokenSource();
HttpResponseMessage response = await client.SendRequestAsync(request).AsTask(tokenSource.Token, progressCallback);
IInputStream inputStream = await response.Content.ReadAsInputStreamAsync();
StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.GenerateUniqueName);
// Copy from stream to stream.
IOutputStream outputStream = await file.OpenAsync(FileAccessMode.ReadWrite);
await RandomAccessStream.CopyAndCloseAsync(inputStream, outputStream);
}
private void OnSendRequestProgress(HttpProgress obj)
{
Debug.WriteLine(obj);
}
Otherwise, take a look at this other answer.

Categories

Resources