使用MVC 3以正确的方式在DB中存储和检索文件

时间:2011-10-12 16:33:03

标签: c# asp.net-mvc-3 file-io blob

我有一个简单的反馈表单,允许我的用户记录反馈,并可选择上传与问题相关的文件。文件可以是任何格式,而不仅仅是图像。

控制器上的服务器端代码如下所示:

    [HttpPost]
    public ActionResult Create(Entry entry)
    {
        try
        {
            foreach (string inputTagName in Request.Files)
            {
                HttpPostedFileBase file = Request.Files[inputTagName];

                if (file != null && file.ContentLength > 0)
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        file.InputStream.CopyTo(ms);

                        db.Files.Add(new Models.File
                        {
                            Entry = entry,
                            FileName = Path.GetFileName(file.FileName),
                            FileContents = ms.GetBuffer()
                        });
                    }
                }
            }

            entry.Status = Status.Open;
            entry.Severity = Severity.Medium;
            entry.DateSubmitted = DateTime.Now;

            db.Entries.Add(entry);
            db.SaveChanges();

            return View("Complete");
        }
        catch
        {
            return View("Error");
        }
    }

我还有一个控制器动作,可让我将整个数据库下载到一个zip中并发送到我的浏览器:

    public ActionResult Download()
    {
        MemoryStream fileStream = new MemoryStream();
        StringBuilder csv = new StringBuilder();
        csv.AppendLine("Id,Summary,Description,Company,Name,Email,Telephone,Version,Area,Date Submitted,Notes,Resolution,Date Resolved");

        using (ZipFile zip = new ZipFile())
        {
            foreach (Entry entry in db.Entries.ToList())
            {
                csv.AppendFormat("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12}",
                                 entry.Id,
                                 entry.Summary,
                                 entry.Description,
                                 entry.Company.Name,
                                 entry.Name,
                                 entry.Email,
                                 entry.Telephone,
                                 entry.Version.Number,
                                 entry.Area,
                                 entry.DateSubmitted,
                                 entry.Notes,
                                 entry.Resolution,
                                 entry.DateResolved);

                if (entry.Files.Count > 0)
                {
                    foreach (FeedbackManager.Models.File file in entry.Files)
                    {
                        using (MemoryStream ms = new MemoryStream())
                        {
                            ms.Write(file.FileContents, 0, file.FileContents.Length);
                            ms.Flush();
                            zip.AddEntry(entry.Id+"_"+file.FileName, ms.GetBuffer());
                        }
                    }
                }
            }

            zip.AddEntry("feedback.csv", csv.ToString());

            zip.Save(fileStream);
        }

        return File(fileStream.GetBuffer(), "application/zip", String.Format("FeedbackToDate_{0}.zip", DateTime.Now.Date.ToShortDateString()));
    }

问题是我正在读取数据库中的文件数据,zip文件被破坏了一些如何和我无法打开它,如果我排除文件,我可以打开zip文件,我可以读取csv罚款。

将这些文件从数据库中拉出来的正确方法是什么,我是否需要先保存到文件系统?文件数据是如何被破坏的?如何保存原始二进制数据以使内容不受影响?

由于

2 个答案:

答案 0 :(得分:3)

使用MemoryStream.ToArray()代替MemoryStream.GetBuffer() - > http://msdn.microsoft.com/en-us/library/system.io.memorystream.toarray.aspx

MemoryStream.GetBuffer()也可能返回不属于内容的未使用字节。

答案 1 :(得分:0)

您假设数据未正确放入数据库。

上传文件时,您应该执行以下操作:

 int FileLen;
 System.IO.Stream MyStream;

 FileLen = file.ContentLength;
 byte[] input = new byte[FileLen];

 MyStream = file.InputStream;
 MyStream.Read(input, 0, FileLen);

然后将输入分配给数据库字段,如下所示:

FileContents = input;

我不确定您使用的是什么作为后端数据库,但如果您使用的是2008,请使用varbinary(max)数据类型。