ASP.NET How to Stream File to User

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



Leave a reply



Submit