Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Web API download locks file

I'm having a small issue with a WebAPI method that downloads a file when the user calls the route of the method.

The method itself is rather simple:

public HttpResponseMessage Download(string fileId, string extension)
{
    var location = ConfigurationManager.AppSettings["FilesDownloadLocation"];
    var path = HttpContext.Current.Server.MapPath(location) + fileId + "." + extension;

    var result = new HttpResponseMessage(HttpStatusCode.OK);
    var stream = new FileStream(path, FileMode.Open);
    result.Content = new StreamContent(stream);
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    return result;
}

The method works as expected - the first time I call it. The file is transmitted and my browser starts downloading the file.

However - if I call the same URL again from either my own computer or from any other - I get an error saying:

The process cannot access the file 'D:\...\App_Data\pdfs\test-file.pdf' because it is being used by another process.

This error persists for about a minute - and then I can download the file again - but only once - and then I have to wait another minute or so until the file is unlocked.

Please note that my files are rather large (100-800 MB).

Am I missing something in my method? It almost seems like the stream locks the file for some time or something like that?

Thanks :)

like image 986
JBuus Avatar asked Mar 13 '23 10:03

JBuus


1 Answers

It is because your file is locked by the first stream, you must specify a FileShare that allow it to be opened by multiple streams :

public HttpResponseMessage Download(string fileId, string extension)
{
    var location = ConfigurationManager.AppSettings["FilesDownloadLocation"];
    var path = HttpContext.Current.Server.MapPath(location) + fileId + "." + extension;

    var result = new HttpResponseMessage(HttpStatusCode.OK);
    var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
    result.Content = new StreamContent(stream);
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    return result;
}

Like that you allow multiple stream to open this file for read only.

See the MSDN documentation on that constructor overload.

like image 57
Fabien ESCOFFIER Avatar answered Mar 24 '23 03:03

Fabien ESCOFFIER