0

我有以下 ActionResult:

[Authorize]
public ActionResult DownloadFile(Guid id)
{
    AdjusterFile file = (from f in db.AdjusterFiles
                         join a in db.Adjusters
                         on f.adjusterID equals a.id
                         join u in db.Users
                         on a.userID equals u.id
                         where u.username == HttpContext.User.Identity.Name
                         && f.id == id
                         select f)
                        .FirstOrDefault();

    return new FileContentResult(file.fileContent.ToArray(), file.fileContentType);
}

它非常适用于 word 文档 (DOC/DOCX)。但是,每当我尝试下载由同一进程上传的 PDF 时,它会在 Chrome 中显示“无法加载 PDF 文档”。在 IE 中显示“文件已损坏,无法修复”。

内容类型是“应用程序/pdf”。

如何在 MVC 中下载 PDF?

相关文件上传代码:

using (MemoryStream ms = new MemoryStream())
{
    file.InputStream.CopyTo(ms);
    byte[] array = ms.GetBuffer();

    AdjusterFile newFile = new AdjusterFile();

    newFile.id = Guid.NewGuid();
    newFile.adjusterID = adj.id;
    newFile.type = "eo";
    newFile.fileName = file.FileName;
    newFile.fileContent = array;
    newFile.fileContentType = file.ContentType;

    db.AdjusterFiles.InsertOnSubmit(newFile);
}
4

1 回答 1

3

你不需要 MemoryStream,试试这样:

byte[] array = new byte[file.ContentLength];
file.InputStream.Read(array, 0, array.Length);

AdjusterFile newFile = new AdjusterFile();

newFile.id = Guid.NewGuid();
newFile.adjusterID = adj.id;
newFile.type = "eo";
newFile.fileName = file.FileName;
newFile.fileContent = array;
newFile.fileContentType = file.ContentType;

db.AdjusterFiles.InsertOnSubmit(newFile);

您的代码不起作用的原因在于GetBytes您在 MemoryStream 上使用的方法的 MSDN 文档中的以下引用:

请注意,缓冲区包含可能未使用的已分配字节。例如,如果将字符串“test”写入 MemoryStream 对象,则从 GetBuffer 返回的缓冲区长度为 256,而不是 4,其中 252 个字节未使用。要仅获取缓冲区中的数据,请使用 ToArray 方法;但是,ToArray 会在内存中创建数据的副本。

因此,基本上使用 GetBytes 方法,您可能并不总是获得写入流的确切字节。或者,您可以使用ms.ToArray()在您的场景中表现正确的方法,但老实说,您根本不需要这个 MemoryStream。您只是分配了一些不必要的空间,您可以直接将上传文件的内容读入字节数组,如我的回答所示。

重要说明:我希望您意识到通过将整个字节数组加载到内存中,您的网络服务器上的内存消耗可能会增长得非常快,尤其是当您开始处理大文件时。理想的解决方案是将文件存储在文件系统上,或者如果您使用的是 MS SQL 2008 或更高版本,则可以利用新的 FILESTREAM 类型。

于 2013-07-10T14:38:58.550 回答