Download/Stream file from URL - asp.net
You could use HttpWebRequest to get the file and stream it back to the client. This allows you to get the file with a url. An example of this that I found ( but can't remember where to give credit ) is
//Create a stream for the file
Stream stream = null;
//This controls how many bytes to read at a time and send to the client
int bytesToRead = 10000;
// Buffer to read bytes in chunk size specified above
byte[] buffer = new Byte[bytesToRead];
// The number of bytes read
try
{
//Create a WebRequest to get the file
HttpWebRequest fileReq = (HttpWebRequest) HttpWebRequest.Create(url);
//Create a response for this request
HttpWebResponse fileResp = (HttpWebResponse) fileReq.GetResponse();
if (fileReq.ContentLength > 0)
fileResp.ContentLength = fileReq.ContentLength;
//Get the Stream returned from the response
stream = fileResp.GetResponseStream();
// prepare the response to the client. resp is the client Response
var resp = HttpContext.Current.Response;
//Indicate the type of data being sent
resp.ContentType = MediaTypeNames.Application.Octet;
//Name the file
resp.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());
int length;
do
{
// Verify that the client is connected.
if (resp.IsClientConnected)
{
// Read data into the buffer.
length = stream.Read(buffer, 0, bytesToRead);
// and write it out to the response's output stream
resp.OutputStream.Write(buffer, 0, length);
// Flush the data
resp.Flush();
//Clear the buffer
buffer = new Byte[bytesToRead];
}
else
{
// cancel the download if client has disconnected
length = -1;
}
} while (length > 0); //Repeat until no data is read
}
finally
{
if (stream != null)
{
//Close the input stream
stream.Close();
}
}
ASP.NET How To Stream File To User
I wouldn't call Response.Close()
or Response.End()
.
Response.End()
will stop the page execution/rendering at that point. No code following Response.End()
will be run. The response is terminated at that point with no further output added to the stream.
Response.Close()
is similar to Response.End()
, but allows code to be executed after it is called (but no further output can be sent in the page response).
Response.Flush()
will send any remaining response items to the page.
From an IIS core team member:
Response.Close sends a reset packet to
the client and using it in anything
other than error condition will lead
to all sorts of problems - eg, if you
are talking to a client with enough
latency, the reset packet can cause
any other response data buffered on
the server, client or somewhere in
between to be dropped.In this particular case, compression
involves looking for common patterns
within the response and some amount of
response has to be buffered by the
compression code to increase the
chance of finding longer repeating
patterns - this part that is buffered
cannot be sent to the client once you
do Response.Close().In short, do not use Response.Close().
How to stream file from disk to client browser in .Net MVC
Ok, I came across this forum discussion: http://forums.asp.net/t/1408527.aspx
Works like a charm, exactly what I need!
UPDATE
Came across this question How to deliver big files in ASP.NET Response? and it turns out it's much simpler, here is how I do it now:
var length = new System.IO.FileInfo(Server.MapPath(filePath)).Length;
Response.BufferOutput = false;
Response.AddHeader("Content-Length", length.ToString());
return File(Server.MapPath(filePath), System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
Streaming files using HTTP GET : ASP .NET CORE API
In ASP.NET Core, you need to be using an IActionResult if you are sending a custom response. All other responses will be serialized (JSON by default) and sent as response body.
Refer to the answer at File Streaming in ASP.NET Core
How to serve video file / stream from ASP Net Core 6 Minimal API
You can use the Results.Stream()
method to return a stream from a minimal api.
string wwwroot = builder.Environment.WebRootPath;
...
app.MapGet("/video", () =>
{
string filePath = Path.Combine(wwwroot, "test.mp4");
return Results.Stream(new FileStream(filePath, FileMode.Open));
});
The stream parameter is disposed after the response is sent.
Results.Stream
takes a few other optional parameters such as fileDownloadName
, and contentType
(which defaults to "application/octet-stream"
) that might be useful to you. Set enableRangeProcessing: true
to enable range requests.
The above could easily be adapted to take a filename
as a parameter, if you wish. You would need to consider validation (applies equally to the current code TBH). Tested and working for me.
How Stream files in User Request Without Buffering Request in memory or disk in ASP.Net
Ty for answers!.
the main problem was buffering all request in memory (and disk).
i searched and found some help full articles. but i have no reputation to link them! LOL
at all i used this way to solve problem.
this is code:
[RequestAuthorized(CurrentUser = UserTypes.AdminDeveloper)]
public async Task<ActionResult> Create_Step4()
{
...blabla
var requestStream = HttpContext.Request.GetBufferlessInputStream();
var mpp = new MultipartPartParser(requestStream);
long fileSize = FTPUtility.UploadFile(FilePath, mpp);
}
and
public static long UploadFile(string FilePath, MultipartPartParser file)
{
try
{
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(ftpURL + FilePath.Substring(1).Replace('\\', '/'));
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
ftpRequest.Credentials = new NetworkCredential(UserName, Password);
Stream requestStream = ftpRequest.GetRequestStream();
long fileSize = 0;
Byte[] buffer = new Byte[buferSize];
int bytesRead = file.Read(buffer, 0, buferSize);
fileSize += bytesRead;
while (bytesRead > 0)
{
requestStream.Write(buffer, 0, bytesRead);
bytesRead = file.Read(buffer, 0, buferSize);
fileSize += bytesRead;
}
requestStream.Close();
return fileSize;
}
catch (Exception)
{
return -1;
}
}
Streaming an in-memory generated file in ASP.NET Core
There isn't a PushStreamContext
kind of type built-in to ASP.NET Core. You can, however, build your own FileCallbackResult
which does the same thing. This example code should do it:
public class FileCallbackResult : FileResult
{
private Func<Stream, ActionContext, Task> _callback;
public FileCallbackResult(MediaTypeHeaderValue contentType, Func<Stream, ActionContext, Task> callback)
: base(contentType?.ToString())
{
if (callback == null)
throw new ArgumentNullException(nameof(callback));
_callback = callback;
}
public override Task ExecuteResultAsync(ActionContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
var executor = new FileCallbackResultExecutor(context.HttpContext.RequestServices.GetRequiredService<ILoggerFactory>());
return executor.ExecuteAsync(context, this);
}
private sealed class FileCallbackResultExecutor : FileResultExecutorBase
{
public FileCallbackResultExecutor(ILoggerFactory loggerFactory)
: base(CreateLogger<FileCallbackResultExecutor>(loggerFactory))
{
}
public Task ExecuteAsync(ActionContext context, FileCallbackResult result)
{
SetHeadersAndLog(context, result, null);
return result._callback(context.HttpContext.Response.Body, context);
}
}
}
Usage:
[HttpGet("csv")]
public IActionResult GetCSV(long id)
{
return new FileCallbackResult(new MediaTypeHeaderValue("text/csv"), async (outputStream, _) =>
{
var data = await GetData(id);
var records = _csvGenerator.GenerateRecords(data);
var writer = new StreamWriter(outputStream);
var csv = new CsvWriter(writer);
csv.WriteRecords(stream, records);
await writer.FlushAsync();
})
{
FileDownloadName = "results.csv"
};
}
Bear in mind that FileCallbackResult
has the same limitations as PushStreamContext
: that if an error occurs in the callback, the web server has no good way of notifying the client of that error. All you can do is propagate the exception, which will cause ASP.NET to clamp the connection shut early, so clients get a "connection unexpectedly closed" or "download aborted" error. This is because HTTP sends the error code first, in the header, before the body starts streaming.
Related Topics
Ienumerable Doesn't Have a Count Method
Parsing Performance (If, Tryparse, Try-Catch)
C# Printing Problem (Richtextbox)
Caliburn.Micro Serialization Issue When Implementing Propertychangedbase
Exception Using Copytodatatable with "New {..}" Linq Query
Entity Framework - Add Navigation Property Manually
View Post Request Body in Application Insights
Custom Path of the User.Config
How to Ignore a Property When Serializing Using the Datacontractserializer
How to Get the Value of Private Field Using Reflection
How to Send a File and Form Data with Httpclient in C#
Preprocessor Directive in C# for Importing Based on Platform
Generics: Casting and Value Types, Why Is This Illegal
Unity - Checking If the Player Is Grounded Not Working
Crud Operations Using Datagridview, Datatable and Dataadapter - Cannot Add New Row to Datagridview