我有一个基于实体框架和 Microsoft SQL Server 2008 构建的 ASP.NET MVC 解决方案。我需要创建一个允许用户上传文件的函数。
我想要的是:
在实体模型中,将 BLOB 数据库列映射到
byte[]
属性。将上传文件的内容分配给实体对象的该属性,并将更改保存在 ObjectContext
.
MD5CryptoServiceProvider
类
在 SQL Server 2008 数据库中存储文件的“正确”方法是 使用 FILESTREAM 数据类型。我不知道实体框架是否支持这一点,但您当然可以尝试看看会发生什么。
也就是说,大多数时候,当人们这样做时,他们不会将文件存储在数据库中。这样做意味着您需要通过 ASP.NET 和数据库服务器来提供可以直接从 Web 服务器提供的文件。它还可能会使数据库和站点的备份情况变得有些复杂。因此,当我们将文件上传到 MVC/实体框架时,我们仅存储对数据库中文件位置的引用,并将文件本身存储在其他位置。
显然,哪种策略适合您在很大程度上取决于您的应用程序的具体情况。
这是我对播客的做法:
ID 标题 路径 摘要 上传日期 --- ----- -------------------- ---------------- ----------- 1 TestPodcast /Podcasts/ep1.mp3 一个测试播客 2010-02-12
path
存储对播客物理位置的引用。我使用了 Scott Hanselman 的一篇关于 File Uploads with ASP.NET MVC 的文章来处理文件上传部分。
基于@Thomas的答案的工作示例(仅用于文件上传,因为这个在谷歌中排在第一位):
public void AddDocument(HttpPostedFileBase file)
{
try
{
using (TransactionScope scope = new TransactionScope())
{
try
{
using (var ctx = new Entities())
{
EntityDoc doc = new EntityDoc(); //The document table
doc.DocumentFileName = file.FileName; //The file Name
using (var reader = new System.IO.BinaryReader(file.InputStream))
{
doc.DocumentFile = reader.ReadBytes(file.ContentLength); // the Byte [] Field
}
ctx.EntityDocs.Add(doc);
ctx.SaveChanges();
scope.Complete();
}
}
catch (Exception ex)
{
throw ex;
}
}
}
catch (Exception ex)
{
throw ex;
}
}
我认为用数据库存储文件的最佳方法是在服务器中仅存储该文件的字符串路径(换句话说,将文件存储在文件夹中,而在数据库中仅存储其字符串路径)。我使用类似的东西(还有随机命名系统,以避免许多用户之间出现相同的命名问题,同时将所有数据保存在同一个文件夹中):
public static class FileExtensions
{
public static string RootPath { get; set; }
public static bool IsValidSize(this IFormFile file, float kb = 20)
=> file.Length <= kb * 1024;
public static bool IsCorrectType(this IFormFile file, string contentType = "image")
=> file.ContentType.Contains(contentType);
public static async Task<string> SaveAsync(this IFormFile file, string path = "data")
{
string extension = Path.GetExtension(file.FileName);
string fileName = Path.GetFileNameWithoutExtension(file.FileName).Length > 32 ?
file.FileName.Substring(0, 32) :
Path.GetFileNameWithoutExtension(file.FileName);
fileName = Path.Combine(path, Path.GetRandomFileName() + fileName + extension);
using (FileStream fs = File.Create(Path.Combine(RootPath, fileName)))
{
await file.CopyToAsync(fs);
}
return fileName;
}
}