【问题标题】:ASP.NET CORE FILE upload issueASP.NET CORE 文件上传问题
【发布时间】:2017-11-26 20:03:36
【问题描述】:

我有一个适用于 chrome 的文件上传代码,但在 IE 上会引发以下错误。

"IOException: 进程无法访问文件 'path\filename',因为它正被另一个进程使用。 System.IO.__Error.WinIOError(int errorCode, string maybeFullPath) System.IO.FileStream.Init(字符串路径,FileMode 模式,FileAccess 访问,int 权限,bool useRights,FileShare share,int bufferSize,FileOptions 选项,SECURITY_ATTRIBUTES secAttrs,字符串 msgPath,bool bFromProxy,bool useLongPath,bool checkHost) System.IO.FileStream..ctor(字符串路径、FileMode模式、FileAccess访问、FileShare共享) System.IO.File.OpenWrite(字符串路径) RES.Controllers.DataHandling.DataUploadController+d__5.MoveNext() 在 DataUploadController.cs +

控制器动作方法如下:

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);

                    }
    }
}

查看下面的模型:

 public class UploadedData
    {

        public IFormFile File { get; set; }
    }

我可以想象代码没有任何问题,因为它适用于 Chrome。有谁知道 IE 的问题是什么?

【问题讨论】:

  • filename 是什么?请显示完整的[HttpPost] Upload 方法。
  • 添加了http post方法和视图模型
  • 使用 (var stream = System.IO.File.OpenWrite(filename)) { await file.CopyToAsync(stream); }
  • 如果您查看异常消息,很明显:System.IO.File.OpenWrite(filename)

标签: c# asp.net asp.net-mvc google-chrome internet-explorer


【解决方案1】:

这是由于 Internet Explorer 和 Chrome 之间的行为不同造成的。 出于安全原因,Chrome 会隐藏用户目录的路径。
这意味着您只能获取变量中的文件名(例如myfile.txt)。

虽然 Internet Explorer 会为您提供上传文件的完整客户端路径 (C:\Users\User1\myfile.txt)。

Path.Combine 然后失败并返回客户端路径(例如C:\Users\User1\myfile.txt),而不是您上传目录的组合路径。

您的服务器无法打开该文件,因为在您的测试/开发环境中该文件是由您的浏览器打开的。

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

parsedContentDisposition.FileName 周围设置Path.GetFileName(..) 可以解决这个问题。

简而言之:

Path.Combine 在 IE 中尝试组合 D:\UploadedFilesC:\Users\User1\myfile.txt,这会导致 C:\Users\User1\myfile.txt 并失败。

Chrome 中的Path.Combine 尝试将D:\UploadedFilesmyfile.txt 组合成D:\UploadedFiles\myfile.txt 并成功。

我认为这种行为是由于 Chrome 和 Firefox 中的这种安全机制造成的,在 this question on Stack Overflow 上进行了讨论。

编辑: Internet Explorer 仅上传本地 Intranet 区域内标准设置的完整路径。

【讨论】:

  • 太好了,这是一个很好的解释,确实解决了问题。
【解决方案2】:

我最近遇到了这个问题并找到了解决方案。这是我的控制器,它从视图中的表单接收一些数据和一些文件。基本上,它将文件保存在 wwwRoot 之外的名为“Documents”的文件夹中。它还会覆盖具有相同名称的文件。这是一个非常基本的示例,因此需要进行一些检查和错误处理。 请注意,Edge 会将文件名保存为完整路径名,因此请在之后更改名称以适应它。

[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;
   }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-28
    • 1970-01-01
    • 2021-08-02
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多