网站链接: 我爱捣鼓
当前位置: 首页 > web开发  > MVC

ASP.NET MVC4上传图片到数据库的实例源码

2021/4/13 21:03:06

从前我们经常会用程序上传图片到服务器的指定文件目录,今天我们就来说说通过asp.net/mvc WEB应用程序如何上传图片到数据库以及如何在WEB页面上显示图片。数据库表对应整个Model类,不单图片数据一个字段,我们从数据表的定义开始:CREATE TABLE [dbo].[Products] ( […

从前我们经常会用程序上传图片到服务器的指定文件目录,今天我们就来说说通过asp.net/mvc WEB应用程序如何上传图片到数据库以及如何在WEB页面上显示图片。数据库表对应整个Model类,不单图片数据一个字段,我们从数据表的定义开始:

CREATE TABLE [dbo].[Products] (
    [ProductID]     INT             IDENTITY (1, 1) NOT NULL,
    [Name]          NVARCHAR (MAX)  NOT NULL,
    [Description]   NVARCHAR (MAX)  NOT NULL,
    [Price]         DECIMAL (18, 2) NOT NULL,
    [Category]      NVARCHAR (MAX)  NOT NULL,
    [ImageData]     VARBINARY (MAX) NULL,
    [ImageMimeType] NVARCHAR (MAX)  NULL,
    CONSTRAINT [PK_dbo.Products] PRIMARY KEY CLUSTERED ([ProductID] ASC)
);

保存图片的字段为ImageData,类型VARBINARY,字段ImageMimeType保存图片的类型。我们使用Entity framework处理c#对象到数据库的操作,我们不需要编写代码通过SQL代码操作数据库,Entity framework负责数据库的操作。Entity framework支持Model first和Code-first两种方式,Code-first先编写c# model类,然后绑定到数据库,相关的内容可以参见http://msdn.microsoft.com/en-us/data/jj200620。

从Model类开始: 

public class Product {
        [HiddenInput(DisplayValue = false)]
        public int ProductID { get; set; }
        [Required(ErrorMessage = "Please enter a product name")]
        public string Name { get; set; }
        [DataType(DataType.MultilineText)]
        [Required(ErrorMessage = "Please enter a description")]
        public string Description { get; set; }
        [Required]
        [Range(0.01, double.MaxValue, ErrorMessage = "Please enter a positive price")] 
        public decimal Price { get; set; }
        [Required(ErrorMessage = "Please specify a category")]
        public string Category { get; set; }
        public byte[] ImageData { get; set; }
        [HiddenInput(DisplayValue = false)]
        public string ImageMimeType { get; set; }
    }

Entity framework可以在VS中使用nuget package manager安装,安装完entity framework我们创建Entity framework的会话类将Model和数据库联系起来:

using System.Data.Entity;
namespace SportsStore.Domain.Concrete {
    public class EFDbContext : DbContext {
        public DbSet<Product> Products { get; set; }
    }
}


接下来创建一个使用EFDbContext操作Model的辅助类:

public interface IProductRepository {
        IQueryable<Product> Products { get; }
        void SaveProduct(Product product);
        Product DeleteProduct(int productID);
    }
public class EFProductRepository : IProductRepository
    {
        private EFDbContext context = new EFDbContext();
        public IQueryable<Product> Products
        {
            get { return context.Products; }
        }
        public void SaveProduct(Product product)
        {
            if (product.ProductID == 0)
            {
                context.Products.Add(product);
            }
            else
            {
                Product dbEntry = context.Products.Find(product.ProductID);
                if (dbEntry != null)
                {
                    dbEntry.Name = product.Name;
                    dbEntry.Description = product.Description;
                    dbEntry.Price = product.Price;
                    dbEntry.Category = product.Category;
                    dbEntry.ImageData = product.ImageData;
                    dbEntry.ImageMimeType = product.ImageMimeType;
                }
            }
            context.SaveChanges();
        }
        public Product DeleteProduct(int productID)
        {
            Product dbEntry = context.Products.Find(productID);
            if (dbEntry != null)
            {
                context.Products.Remove(dbEntry);
                context.SaveChanges();
            }
            return dbEntry;
        }
    }

定义IProductRepository接口是方便后续使用Dependency injection从接口获取实现类EFProductRepository的实例,这里就不列出具体如何实现。EFProductRepository使用EFDbContext完成添加、保存对象到数据库以及从数据库删除对象。完成数据模型的操作,下面定义控制器的方法:

public class AdminController : Controller {
private IProductRepository repository;
public AdminController(IProductRepository repo) {
    repository = repo;
}
public ViewResult Index() {
    return View(repository.Products);
}
public ViewResult Edit(int productId) {
    Product product = repository.Products
.FirstOrDefault(p => p.ProductID == productId);
    return View(product);
}
[HttpPost]
public ActionResult Edit(Product product, HttpPostedFileBase image) {
    if (ModelState.IsValid) {
if (image != null) {
    product.ImageMimeType = image.ContentType;
    product.ImageData = new byte[image.ContentLength];
    image.InputStream.Read(product.ImageData, 0, image.ContentLength);
}
repository.SaveProduct(product);
TempData["message"] = string.Format("{0} has been saved", product.Name);
return RedirectToAction("Index");
    } else {
// there is something wrong with the data values
return View(product);
    }
}
public ViewResult Create() {
    return View("Edit", new Product());
}
[HttpPost]
public ActionResult Delete(int productId) {
    Product deletedProduct = repository.DeleteProduct(productId);
    if (deletedProduct != null) {
TempData["message"] = string.Format("{0} was deleted", 
    deletedProduct.Name);
    }
    return RedirectToAction("Index");
}
}

这里两个Edit ation,第一个显示编辑上传页面,带HttpPost特性的用于处理编辑页面提交回传,提交的image数据为HttpPostedFileBase类型,我们从中取出图像文件的数据保存到Model类的ImageData属性,ContentType则记录到ImageMimeType属性。对应的Edit视图:


@model SportsStore.Domain.Entities.Product
@{
    ViewBag.Title = "Admin: Edit " + @Model.Name;
    Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
<h1>Edit @Model.Name</h1>
@using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype = "multipart/form-data" })) {
    
    @Html.EditorForModel()
    <div class="editor-label">Image</div>
    <div class="editor-field">
        @if (Model.ImageData == null) {
            @:None
        } else {
            <img width="150" height="150" src="@Url.Action("GetImage", "Product", new { Model.ProductID })" />
        }
        <div>Upload new image: <input type="file" name="Image" /></div>
    </div>
        
    <input type="submit" value="Save" />
    @Html.ActionLink("Cancel and return to List", "Index")
}

这里指定表单的enctype=multipart/form-data,缺少这个属性表单提交的数据中会只有图片文件的名称而不包含图片文件的数据。图片显示img单元的src指向一个从product的action生成的网址,我们还需要实现这个方法:

public FileContentResult GetImage(int productId) { 
  Product prod = repository.Products.FirstOrDefault(p => p.ProductID == productId); 
  if (prod != null) { 
    return File(prod.ImageData, prod.ImageMimeType); 
  } else { 
    return null; 
  } 
}

这里从图片文件数据和mime类型返回一个FileContentResult。

这就是Asp.net/MVC实现上传图片到数据库的完整过程,实际的应用中我们还需要限制文件大小,通过文件后缀名或者ContentType检查是否是有效的图片文件,感谢您访问“我爱捣鼓(www.woaidaogu.com)”网站的内容,希望对大家有所帮助!引用本文内容时,请注明出处!谢谢合作!

相关资讯

  • C#如何实现图片马赛克效果处理?

    我们经常会看到图片上面打上马赛克,一般人都会想到ps,如果通过C#程序如何实现了,可以看看下面的源码:using System.Drawing;using System.Drawing.Imaging;using System.Web.Mvc; namespace MVC2017_Sample.Controllers{ public class DefaultController : Control…

    2021/3/4 21:55:08
  • mvc中如何将控制器的数据赋值给视图的js对象json?

    mvc中如何将控制器的数据赋值给视图的js对象,其实非常简单,话不多说,直接看源码吧!cshtml页面@{ Layout = null;} <!DOCTYPE html><html><head> <meta name="viewport" content="width=device-width" /> <ti…

    2021/3/4 21:51:09