ASP.NET MVC中的多个文件上载多次上载单个文件

时间:2018-08-22 19:59:10

标签: c# asp.net-mvc azure file-upload

我有一个ASP.NET MVC项目,用户可以在其中一次上传多个文件。视图中包含以下代码:

@using (Html.BeginForm("Edit",
            "Bacteria",
            FormMethod.Post,
            new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
<!--Other fields that are posted correctly to the db-->
 <div class="">
    <label class="control-label col-md-2">Attach New Files:</label>
    <div class="col-md-10">
        <input type="file" id="Attachment" name="Attachment" class="form-control" accept=".xls,.xlsx,.csv,.CSV,.png,.jpeg,.jpg,.gif,.doc,.docx,.pdf,.PDF" multiple />
    </div>
</div>
<div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <input type="submit" value="Save" class="btn btn-default" />
    </div>
</div>

控制器中的方法是:

if (ModelState.IsValid)
{
    db.Entry(bacteria).State = EntityState.Modified;
    db.SaveChanges();

    foreach (string file in Request.Files)
    {
        HttpPostedFileBase hpf = Request.Files[file];
        var fileName = Path.GetFileName(hpf.FileName);
        if (fileName == null || fileName == "")
        {
            break;
        }
        var subPath = "Attachments/Bacteria/" + bacteria.ID + "/";
        bool exists = System.IO.Directory.Exists(Server.MapPath("~/" + subPath));
        if (!exists)
        {
            System.IO.Directory.CreateDirectory(Server.MapPath("~/" + subPath));
        }
        var path = Path.Combine(subPath, fileName);
        hpf.SaveAs(Server.MapPath("~/" + path));
        BacteriaAttachment a = new BacteriaAttachment()
        {
            Name = fileName,
            Bacteria = bacteria,
            Link = path
         };
         db.BacteriaAttachments.Add(a);
         db.SaveChanges();
    }
}

如果我上传FileOne.png,FileTwo.png,FileThree.png; BacteriaAttachements表将获得3条新记录,它们都具有相同的名称(例如FileOne.png),链接和细菌ID。只有它们的ID(主键)是唯一的。服务器中仅上传了一个文件(例如FileOne.png)。

因此,不是上传三个文件,而是其中三个文件被上传了三次。

非常感谢您的帮助。

谢谢。

2 个答案:

答案 0 :(得分:1)

在执行foreach (string file in Request.Files)时,对于每次迭代,file的值将是字符串值"Attachment",这是文件输入的名称。当用户从同一输入上载多个文件时,Request.Files使用相同的键(即输入元素的名称,即“附件”)存储所有文件。现在,当您执行Request.Files["Attachment"]时,它将只给您第一项( ,因为所有项都具有相同的键 )。对于循环的所有迭代,都是这样。

访问Request.Files时,请勿使用基于名称的访问方法,使用基于索引的方法Request.Files[zeroBasedindex])。

您可以使用for循环正确地遍历集合,并使用基于索引的方法读取Request.Files

for(var i = 0; i < Request.Files.Count; i++)
{
    HttpPostedFileBase hpf =  Request.Files[i];
    // Your existing code to save hpf.
}

我个人始终将HttpPostedFileBase的集合用作我的HttpPost动作方法参数或作为我的视图模型中的属性(我将使用参数作为HttpPost动作方法)并将其循环。要记住的重要一点是,您的参数/属性名称应与用于文件上传的输入名称相匹配

public ActionResult Save(List<HttpPostedFileBase> attachment)
{
   foreach(var hpf in attachment)
   {
     // to do : save hpf
   }
   // to do : return something
}

答案 1 :(得分:0)

穆达萨尔·艾哈迈德·汗(Mudassar Ahmed Khan)在这里的解释非常好: https://www.aspsnippets.com/Articles/MVC-HttpPostedFileBase-multiple-files-Upload-multiple-files-using-HttpPostedFileBase-in-ASPNet-MVC.aspx

  

您应该考虑在控制器方法中使用List<HttpPostedFileBase>作为方法参数。然后遍历每个。如下所示;

foreach (HttpPostedFileBase postedFile in postedFiles)
        {
            if (postedFile != null)
            {
                string fileName = Path.GetFileName(postedFile.FileName);

希望这会有所帮助!