Search code examples
c#.netasp.net-mvcstreamfile-permissions

Use FileShare.ReadWrite with HttpPostedFile in ASP.NET MVC


I am using the code below to save a posted file to a server, but that file is being read continually and need to use FileShare.ReadWrite so I don't get a locked error.

 httpRequest.Files[0].SaveAs(filePath);

Below is my reading method, how can I accomplish this with the HttpPosted file is the right way with the best performance.

using (var fileStream = new FileStream(
                   fileLocation,
                   FileMode.Open,
                   FileAccess.Read,
                   FileShare.ReadWrite))
                {
                    using (var streamReader = new StreamReader(fileStream))
                    {
                        xDocument = XDocument.Parse(streamReader.ReadToEnd());
                    }
                }

Is this my best option?

 using (var memoryStream = new MemoryStream())
                {
                    httpRequest.Files[0].InputStream.CopyTo(memoryStream);
                    var bytes = memoryStream.ToArray();

                    using (var fs = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
                    {
                        fs.Write(bytes, 0, bytes.Length);
                    }
                }

Solution

  • Proplem:

    • You want a "Write:Once, Read:Many" Lock

    Assumptions :

    • File is small (average write opration is 5000 ms)
    • No other write or read oprations (Only one programe with 2 function)
    • You read the file a lot more than you write to it

    Solution

    
        using System;
        using System.IO;
        using System.Threading;
        using System.Web.Mvc;
    
        namespace stackoverflow_56307594.Controllers
        {
    
            public class HomeController : Controller
            {
    
                public ActionResult A()
                {
                    readFile();
                    return View();
                }
    
                public ActionResult B()
                {
                    writeFile();
                    return View();
                }
    
    
                private static object writeLock = new Object();
    
                private void readFile()
                {
                    while (!Monitor.TryEnter(writeLock, 5000)) ; //wait 5000 ms for the writeLock (serializing access)
                    using (var stream = new FileStream("filePath", FileMode.Open, FileAccess.Read, FileShare.Read))
                    using (var reader = new StreamReader(stream))
                    {
                        // active read
                        // xDocument = XDocument.Parse(streamReader.ReadToEnd());
    
                    }
                }
                private void writeFile()
                {
                    lock (writeLock)
                    {
                        FileStream stream = null;
                        while (stream == null) //wait for the active read
                        {
                            try
                            {
                                stream = new FileStream("filePath", FileMode.Open, FileAccess.ReadWrite, FileShare.None);
                            }
                            catch (IOException)
                            {
                            // will fail if active read becase FileShare.None   while (stream == null) will  wait
                        }
                    }
                        Request.Files[0].InputStream.CopyTo(stream);
                    }// unlock
                }
    
            }
        }
    
    

    Note :

    1. I did not test load or simply test the solution on a webserver
    2. I only tested it on paper 😁

    enter image description here

    Refs:

    locking - How long will a C# lock wait, and what if the code crashes during the lock? - Stack Overflow

    c# - Deleting files in use - Stack Overflow

    multithreading - Is there a way to detect if an object is locked? - Stack Overflow

    Implementing Singleton in C# | Microsoft Docs

    c# - Using the same lock for multiple methods - Stack Overflow

    c# - Write-Once, Read-Many Lock - Stack Overflow

    c# lock write once read many - Google Search

    FileShare Enum (System.IO) | Microsoft Docs