尝试使用asp.net核心上传文件

问题描述 投票:0回答:1

我正在从部分共享视图中加载产品图像,我正在尝试使用上一个问题中建议的Ifrom文件。

所以在我的产品控制器中,我有以下方法

编辑

我只想保存文件在数据库中的路径,然后将文件保存在磁盘上,这是实现此目的的正确方法。

public ActionResult FileUpload(ProductImages model)
{
   if (model.Image != null)
   {
      var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
      var filePath = Path.Combine(uploads, GetUniqueName(model.Image.FileName));
            model.Image.CopyTo(new FileStream(filePath, FileMode.Create));
    }
        // to do  : Return something
        return RedirectToAction("Index", "Home");

}

我的产品图像课程

public class ProductImages
{
    [Key]
    public int ProductImageId { get; set; }
    public int ProductID { get; set; }
    public string ProductImageTitle { get; set; }
    public string ProductImageUploadUrl { get; set; }
    public string ProductImageRealPath { get; set; }
    public string ServerIpAddress { get; set; }
    public string ProductImageAltTag { get; set; }
    public int DisplayOrder { get; set; }
    public IFormFile Image { set; get; }
}

我正在通过以下加载的共享布局。

<div class="tab-pane" id="images">
        Product Images
    @await Html.PartialAsync("_ProductPicture", Model)
</div>

这是我的共享视图的代码我认为我对我声明IFormFile的方式做错了

@model solitude.models.ProductImages

   <div class="form-group">

    <form asp-action="FileUpload" enctype="multipart/form-data">

        <input asp-for="ImageCaption" />
        <input asp-for="ImageDescription" />
        <input asp-for="MyImage" />

        <input type="submit" />


        </form>


</div>

我收到以下错误

AggregateException:发生一个或多个错误。 (属性'ProductImages.Image'是一个接口类型('IFormFile')。如果它是一个导航属性,通过将该属性的关系转换为映射的实体类型来手动配置该属性的关系,否则使用'[NotMapped]忽略该属性''属性或在'OnModelCreating'中使用'EntityTypeBuilder.Ignore'。)System.Threading.Tasks.Task.ThrowIfExceptional(bool includeTaskCanceledExceptions)

InvalidOperationException:属性'ProductImages.Image'是接口类型('IFormFile')。如果是导航属性,则通过将此属性转换为映射的实体类型来手动配置此属性的关系,否则使用“[NotMapped]”属性或在“OnModelCreating”中使用“EntityTypeBuilder.Ignore”忽略该属性。

编辑2

[HttpPost]
public ActionResult FileUpload(ProductImageVm model)
{
    if (model.Image != null)
    {
        var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
        var fileId = GetUniqueName(model.Image.FileName);
        var filePath = Path.Combine(uploads, fileId);
        model.Image.CopyTo(new FileStream(filePath, FileMode.Create));

    // to do  : Save the record in ProductImage table
    var pi = new ProductImages { ProductID = model.ProductId };
    pi.ProductImageTitle = model.Title;
    pi.ProductImageRealPath = fileId; //Storing the fileId
    _context.ProductImages.Add(pi);
    _context.SaveChanges();

    }
    return RedirectToAction("Index", "Home");

}

现在,我在另一个表单中加载表单的一件事可能就是这个问题

c# asp.net-core asp.net-core-mvc
1个回答
2
投票

您不应该在实体类中使用IFormFile type属性。根据注释,您希望将图像存储在磁盘中,并将路径存储到表中的图像。因此,只需从实体类定义中删除public IFormFile Image { set; get; }属性即可。

您可以在视图模型中使用IFormFile,该模型用于在视图和操作方法之间传输数据。因此,从视图中创建一个包含所需属性的视图模型

public class ProductImageVm
{
   public int ProductId { set;get;}
   public string Title { set;get;}
   public IFormFile Image { set; get; }
   //Add other properties AS NEEDED by your view
}

现在要上传产品56的图像,创建此视图模型的对象,将ProductId设置为56并发送到GET操作中的视图。在视图中,我们将productId保存在隐藏的表单字段中,当我们需要保存新的ProductImages实体记录时,该字段可以在HttpPost操作中稍后使用。

public IActionResult UploadImage(int productId)
{
  var vm = new ProductImageVm { ProductId=productId};
  return View(vm);
}

和视图,它是我们的视图模型的强类型

@model ProductImageVm    
<form asp-action="FileUpload" asp-controller="Products" method="post"
                                                        enctype="multipart/form-data">    
        <input asp-for="Title" />
        <input asp-for="ProductId" type="hidden" />
        <input asp-for="Image" />    
        <input type="submit" />       
</form>

现在,在您的HttpPost操作方法中,使用与参数相同的视图模型,读取Image属性并将其保存到磁盘并将路径存储在表中。您不需要存储完整路径。您可以存储相对路径。在下面的示例中,我在保存ProductImages实体记录时将唯一文件Id(文件名)存储到ProductImageRealPath属性值。

[HttpPost]
public ActionResult FileUpload(ProductImageVm model)
{
   if (model.Image != null)
   {
      var uploads = Path.Combine(hostingEnvironment.WebRootPath, "uploads");
      var fileId = GetUniqueName(model.Image.FileName);
      var filePath = Path.Combine(uploads,fileId);
      model.Image.CopyTo(new FileStream(filePath, FileMode.Create));
    }
    // to do  : Save the record in ProductImage table
    var pi=new ProductImages { ProductId = model.ProductId};
    pi.ProductImageTitle = model.Title;
    pi.ProductImageRealPath = fileId; //Storing the fileId
    db.ProductImages.Add(pi);
    db.SaveChanges();
    return RedirectToAction("Index", "Home");

}
© www.soinside.com 2019 - 2024. All rights reserved.