3
votes

I have a file upload code that works for chrome but throws the following error for IE.

"IOException: The process cannot access the file 'path\filename' because it is being used by another process. System.IO.__Error.WinIOError(int errorCode, string maybeFullPath) System.IO.FileStream.Init(string path, FileMode mode, FileAccess access, int rights, bool useRights, FileShare share, int bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, string msgPath, bool bFromProxy, bool useLongPath, bool checkHost) System.IO.FileStream..ctor(string path, FileMode mode, FileAccess access, FileShare share) System.IO.File.OpenWrite(string path) RES.Controllers.DataHandling.DataUploadController+d__5.MoveNext() in DataUploadController.cs +

Controller action method below:

public async Task<IActionResult> Upload(UploadedData data)
        {
   var filename=string.Empty;
      if (ModelState.IsValid)
                {
                    var file = data.File;

                    var parsedContentDisposition =
                        ContentDispositionHeaderValue.Parse(file.ContentDisposition);
                     filename = Path.Combine(_hostingEnvironment.ContentRootPath,
                        "UplaodedFiles", parsedContentDisposition.FileName.Trim('"'));


                    using (var stream = System.IO.File.OpenWrite(filename))
                    {
                        await file.CopyToAsync(stream);

                    }
    }
}

View model below:

 public class UploadedData
    {

        public IFormFile File { get; set; }
    }

I can imagine that there is nothing wrong with the code since it works for Chrome. Does anyone have any idea what the problem is with IE?

2
What's filename? Please show the complete [HttpPost] Upload method.jAC
Added the the http post method and the view modelBertrand Paul
using (var stream = System.IO.File.OpenWrite(filename)) { await file.CopyToAsync(stream); }Bertrand Paul
If you look at the exception message, it is obvious which : System.IO.File.OpenWrite(filename)Bertrand Paul

2 Answers

8
votes

This is due to different behaviours between Internet Explorer and Chrome. Chrome hides the path to the user directory for security reasons.
This means you only get the filename in your variable (e.g. myfile.txt).

While Internet Explorer gives you the full client path of the uploaded file (C:\Users\User1\myfile.txt).

Path.Combine fails then and returns the client path (e.g. C:\Users\User1\myfile.txt) instead of the combined path to your upload directory.

Your server can't open the file since in your test/dev environment the file is opened by your browser.

filename = Path.Combine(@"D:\",
               "UploadedFiles", Path.GetFileName(parsedContentDisposition.FileName.Trim('"')));

having Path.GetFileName(..) around parsedContentDisposition.FileName fixes that problem.

In short:

Path.Combine in IE tries to combine D:\, UploadedFiles and C:\Users\User1\myfile.txt which results in C:\Users\User1\myfile.txt and fails.

Path.Combine in Chrome tries to combine D:\, UploadedFiles and myfile.txt which results in D:\UploadedFiles\myfile.txt and suceeds.

I think this behaviour is due to this security mechanism in Chrome and Firefox, discussed on this question on Stack Overflow.

Edit: Internet Explorer only uploads the full path on standard settings within the Local Intranet zone.

0
votes

I had this problem recently and found a solution. This is my controller that recieves some data and some files from a form in a view. Basically it saves the files in a folder outside wwwRoot called "Documents". It also overwrites files with the same name. It's a very basic example so do some checks and error handling. Do note that Edge will save the name of the file as the full pathname, so change the name after to accomodate that.

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> SaveDocument(IList<IFormFile> files, 
HomeViewModel model)
{            
   foreach (IFormFile file in files)
    {
       string name =   
       ContentDispositionHeaderValue.Parse(file.ContentDisposition)
       .FileName.Trim('"');

       var filename = this.EnsureCorrectFilename(name);
       using (FileStream output = System.IO.File.Create(this.GetPathAndFilename(filename)))
                await source.CopyToAsync(output);

    }

        //...maybe save to db and return somewhere
}

private string EnsureCorrectFilename(string filename)
   {
        if (filename.Contains("\\"))
            filename = filename.Substring(filename.LastIndexOf("\\") + 1);

        return filename;
   }

private string GetPathAndFilename(string filename)
   {           
        return _env.ContentRootPath + "\\Documents\\" + filename;
   }