这里演示如何在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; }
}
}

我们还需要告诉Entity framework使用哪个数据库,在web.config添加相应的连接字符串:

...
<connectionStrings>
<add name="EFDbContext" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=SportsStore;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
...

接下来创建一个使用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 == )
{
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, , 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。

这就是实现上传图片到数据库的完整过程,实际的应用中我们还需要限制文件大小,通过文件后缀名或者ContentType检查是否是有效的图片文件。

以上内容摘自《Apress Pro ASP.NET MVC 4》第四版,详见原版 http://www.apress.com/9781430242369

ASP.NET MVC 4 - 上传图片到数据库的更多相关文章

  1. 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  2. [ASP.NET MVC2 系列] ASP.Net MVC教程之《在15分钟内用ASP.Net MVC创建一个电影数据库应用程序》

    [ASP.NET MVC2 系列]      [ASP.NET MVC2 系列] ASP.Net MVC教程之<在15分钟内用ASP.Net MVC创建一个电影数据库应用程序>       ...

  3. ASP.NET MVC+Entity Framework 访问数据库

    Entity Framework 4.1支持代码优先(code first)编程模式:即可以先创建模型类,然后通过配置在EF4.1下动态生成数据库. 下面演示两种情形: 1.代码优先模式下,asp.n ...

  4. ASP.NET MVC导入excel到数据库

    MVC导入excel和webform其实没多大区别,以下为代码: 视图StationImport.cshtml的代码: @{ ViewBag.Title = "StationImport&q ...

  5. 24、ASP.NET MVC入门到精通——数据库仓储

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 业务层调用数据层对象,我不想每次都new一个数据层对象,而是在数据层创建一个仓储,统一管理所有的对象调用. 1.在IDAL项目中,新建IDB ...

  6. ASP.NET MVC入门到精通——数据库仓储

    业务层调用数据层对象,我不想每次都new一个数据层对象,而是在数据层创建一个仓储,统一管理所有的对象调用. 1.在IDAL项目中,新建IDBSession.tt模板   Ctrl+S后自动生成IDBS ...

  7. ASP.net mvc Code First 更新数据库

    code first 数据库迁移步骤如下: 第一步:Add-Migration DataBase_Init 1. Install-Package EntityFramework.zh-Hans –Ve ...

  8. ASP.NET MVC 4 如何避免数据库被自动创建或自动迁移

    保哥说要想避免数据库被自动创建或自动迁移,可以在Global.asax文件里的Application_Start方法中加入: System.Data.Entity.Database.SetInitia ...

  9. Asp.net mvc+EF+Sql Server2008数据库缓存依赖

    1.开启数据库缓存依赖功能(开启对数据库中表Article和ArticleType的缓存) (注:)如果要配置SqlCacheDependency,则需要以命令行的方式执行. aspnet_regsq ...

随机推荐

  1. 一步一步开发sniffer(Winpcap+MFC)(五)莫道无人能识君,其实我懂你的心——解析数据包(转)

    前文已经讲过,解析数据包主要通过analyze_frame()这个函数实现的,实际上并非这个函数完成了所有的功能,其实从名字就可以看出,它只是完成了对“帧”的解析,也就是链路层数据的解析,还有anal ...

  2. jni4net使用小结

    网站首页 http://jni4net.com/ 一个简单的例子: 1)      从这里下载binaries,然后解压缩. https://sourceforge.net/projects/jni4 ...

  3. 图像的视差匹配(Stereo Matching)

    这里要求用我们自己计算得到的视差图和给的视差图作比較来比較我们得到的视差图的好坏程度,我视差图返回的值是计算得到的视差乘以3之后的图,所以在计算时我不是两个值相差大于1,而是大于3.由于两个图像都乘3 ...

  4. pid 控制算法

    http://blog.csdn.net/huangkangying/article/details/78129148 https://zh.wikipedia.org/wiki/PID%E6%8E% ...

  5. MongoDB(1)--简单介绍以及安装

    前段时间接触了NoSql类型的数据库redis,当时是作为缓存server使用的.那么从这篇博客開始学习还有一个非常出名的NoSql数据库:MongoDb.只是眼下还没有在开发其中使用.一步一步来吧. ...

  6. OpenCV 学习笔记 05 人脸检测和识别 AttributeError: module 'cv2' has no attribute 'face'

    1 环境设置: win10 python 3.6.8 opencv 4.0.1 2 尝试的方法 在学习人脸识别中,遇到了没有 cv2 中没有 face 属性.在网上找了几个方法,均没有成功解决掉该问题 ...

  7. PEM文件

    原文链接: http://blog.sina.com.cn/s/blog_489f88710100a59w.html OpenSSL 使用 PEM 文件格式存储证书和密钥.PEM 实质上是 Base6 ...

  8. 译:7.使用Spring MVC服务Web内容

    本指南向您介绍了使用Spring创建“hello world”网站的过程.阅读原文:Serving Web Content with Spring MVC 1. 你将会构建什么? 您将构建一个具有静态 ...

  9. 【转】ubuntu16.04设置python3为默认及一些库的安装

    原文:https://www.cnblogs.com/jokie/p/6933546.html Ubuntu默认Python为2.7,所以安装Python包时安装的为py2的包. 利用alternat ...

  10. IDEA的maven项目中 静态文件编译的问题

    IDEA的maven项目中,默认源代码目录下的xml等资源文件并不会在编译的时候一块打包进classes文件夹,而是直接舍弃掉. 如果使用的是Eclipse,Eclipse的src目录下的xml等资源 ...