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

问题描述:

我从部分共享视图中加载产品图像,我试图使用前一个问题中建议的Ifrom文件。尝试使用asp.net核心上传文件

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

编辑

我只想保存文件的路径在数据库中,然后保存在磁盘上的文件是什么正确的方式来实现这一点。

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

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

   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(布尔 includeTaskCanceledExceptions)

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

编辑2

[HttpPost] 公共的ActionResult文件上传(ProductImageVm模型) { 如果(model.Image!= NULL){ 变种 上传= Path.Combine(hostingEnvironment.WebRootPath ,“上传”); var fileId = GetUniqueName(model.Image.FileName); VAR文件路径= Path.Combine(上载,FILEID); model.Image.CopyTo(新的FileStream(文件路径的FileMode。创建));

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

    } 

现在有一件事我加载另一个表单中的表单会这样你不应该使用IFormFile类型属性在实体类的问题

+0

首先,您希望将文件存储在磁盘和数据库中?对于数据库,您应该在您的实体中使用字节数组作为属性类型。应该在你的视图模型中使用IFormFile。 – Shyju

+0

嗨@Shyju我只想将文件的路径存储在数据库中,然后将文件存储在磁盘上。抱歉应该更清楚。 – rogue39nin

+0

@Shyju我重新调整了编辑的内容,所以我在这个问题上让新人更清楚。 – rogue39nin

。根据评论,您想要将图像存储在磁盘中,并将表格中的图像路径存储在表格中。所以只需从实体类定义中删除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,创建这个视图模型的对象,产品ID设置为56,并发送至您的GET操作的视图需要的特性的视图模型。在视图中,我们将把productId保存在一个隐藏的表单域中,当我们需要保存一个新的ProductImages实体记录时,可以稍后在HttpPost操作中使用它。

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

,并认为,这是强烈的HttpPost操作方法输入到我们的视图模型现在

@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> 

,您使用相同的视图模型的参数,请阅读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"); 

} 
+0

因此,这意味着我需要为我的上传创建一个类,然后只是没有作出,但谢谢 – rogue39nin

+0

是的。将UI层关注与数据访问层分开总是很好的做法。第一步不要在剃刀视图中使用数据访问层实体类。创建特定于视图的视图模型并使用它。 – Shyju

+0

如果记录不存在,我将如何获得产品ID尚未使用我的大部分代码的脚手架,因此如果我是愚蠢的,请原谅我 – rogue39nin