首先,不要将图像保存到数据库中。网上有无数的“指南”建议在 MSSQL 中使用字节数组或“图像”类型。数据库不适用于二进制数据存储。当然,它们会容纳二进制存储,但只是因为你can用 AR-15 搬起石头砸自己的脚,并不意味着你should.
相反,将图像存储在它所属的位置:文件系统。然后,只需引用它在数据库中的路径即可。
现在,处理这一切的最简单方法是使用视图模型。如果您还没有使用视图模型,那么现在是开始的好时机。一般来说,您不想将实际的数据库支持的模型直接发送到视图。在表单中,恶意用户可能会进行各种令人讨厌的数据篡改,即使在简单的视图中,您通常也会传递比他们需要的更多的数据。
因此,第一步是创建一个视图模型Profile
。通常将其命名为ProfileViewModel
or ProfileVM
。然后,在此模型上,您只需添加以下属性Profile
您将在视图中进行编辑或以其他方式与之交互。然后,您实际上可以添加其他属性not也可以在数据库支持的模型上用于特殊用途的视图函数,例如SelectList
与使用DropDownListFor
,所以你实际上可以保持强类型而不是诉诸于ViewBag
对于这样的事情。
对于您的图像,您需要两个字段。我通常会选择以下内容:
public string Photo { get; set; }
public HttpPostedFileBase PhotoUpload { get; set; }
在您的编辑/创建视图中,您将仅引用PhotoUpload
,这将是您的文件上传字段(尽管您可以使用Photo
如果您愿意,也可以显示当前设置的图像)。
@Html.TextBoxFor(m => m.PhotoUpload, new { type = "file" })
然后,要在控制器操作中处理发布的文件:
if (model.PhotoUpload.ContentLength > 0) {
// A file was uploaded
var fileName = Path.GetFileName(model.PhotoUpload.FileName);
var path = Path.Combine(Server.MapPath(uploadPath), fileName);
model.PhotoUpload.SaveAs(path);
model.Photo = uploadPath + fileName;
}
Where uploadPath
应该是您要存储上传图像的主目录相对路径,即类似~/uploads/profile/photos
。确保在尝试发布表单之前创建目录,或者添加一些逻辑来检查目录是否存在并在必要时创建它(但这需要对服务器具有更高的信任,因此在大多数安全性较差的环境中并不理想一个大问题)。
然后,您只需要某种方法将视图模型中的数据映射回数据库支持的模型。您可以手动执行此操作,但使用 AutoMapper 之类的工具将使您的生活变得更加轻松。使用自动映射器(其中model
是一个实例ProfileViewModel
):
var profile = AutoMapper.Mapper.Map<Profile>(model);
或者,由于使用配置文件之类的东西,编辑现有模型比创建新模型更常见:
var profile = db.Profiles.Find(userId);
...
Automapper.Mapper.Map(model, profile);
那么,在您的实际模型上,您将不会有PhotoUpload
财产,只是Photo
。您设置的路径Photo
视图模型上的 将会映射到模型的同名属性上,因此剩下的就是保存更新后的配置文件。
另外,由于您正在谈论上传照片,因此您可能需要添加一些内容类型检查,以确保用户上传的是图像,而不是诸如 Word 文档之类的愚蠢内容。在你之前if (ModelState.IsValid)
检查,添加:
var validTypes = new[] { "image/jpeg", "image/pjpeg", "image/png", "image/gif" };
if (!validTypes.Contains(model.PhotoUpload.ContentType))
{
ModelState.AddModelError("PhotoUpload", "Please upload either a JPG, GIF, or PNG image.");
}
根据需要更改 MIME 类型以匹配您的业务案例。