简体   繁体   English

MVC FileContentResult-适用于DOC而非PDF

[英]MVC FileContentResult - Works for DOC not PDF

I have the following ActionResult: 我有以下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);
}

It works perfectly for word documents (DOC/DOCX). 它非常适合Word文档(DOC / DOCX)。 However, whenever I try to download PDFs which are uploaded by the same process, it says, " Failed to load PDF document " in Chrome. 但是,每当我尝试下载以相同过程上传的PDF时,都会在Chrome中显示“ 无法加载PDF文档 ”。 In IE, it says, " The file is damaged and could not be repaired ." 在IE中,它说:“ 文件已损坏,无法修复 。”

The content type is "application/pdf." 内容类型为“应用程序/ pdf”。

How can I download PDFs in MVC? 如何在MVC中下载PDF?

Relevant file upload code: 相关文件上传代码:

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);
}

You don't need a MemoryStream, try like this: 您不需要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);

The reason why your code doesn't work lies in the following quote from the MSDN documentation of the GetBytes method that you are using on the MemoryStream: 您的代码无法正常工作的原因在于您在MemoryStream上使用的GetBytes方法的MSDN文档中的以下引用:

Note that the buffer contains allocated bytes which might be unused. 请注意,缓冲区包含分配的字节,这些字节可能未使用。 For example, if the string "test" is written into the MemoryStream object, the length of the buffer returned from GetBuffer is 256, not 4, with 252 bytes unused. 例如,如果将字符串“ test”写入MemoryStream对象,则从GetBuffer返回的缓冲区的长度为256,而不是4,未使用252个字节。 To obtain only the data in the buffer, use the ToArray method; 要仅获取缓冲区中的数据,请使用ToArray方法。 however, ToArray creates a copy of the data in memory. 但是,ToArray会在内存中创建数据的副本。

So basically with the GetBytes method you might not always get the exact bytes you have written to the Stream. 因此,基本上,通过GetBytes方法,您可能并不总是获得已写入Stream的确切字节。 Alternatively you could have used the ms.ToArray() method which would have behaved correctly in your scenario, but honestly you don't need this MemoryStream at all. 另外,您可能使用了ms.ToArray()方法,该方法在您的方案中表现正确,但是说实话,您根本不需要此MemoryStream。 You are just allocating some unnecessary space where you could directly read the contents of the upload file into a byte array as shown in my answer. 您只是在分配一些不必要的空间,您可以在其中直接将上载文件的内容读取到字节数组中,如我的答案所示。

Important remark: I hope you realize that by loading the entire byte array in-memory, the memory consumption could grow pretty fast on your webserver especially if you start working with big files. 重要说明:我希望您认识到,通过将整个字节数组加载到内存中,Web服务器上的内存消耗可能会非常快地增长,尤其是当您开始使用大文件时。 The ideal solution would have been to store the file either on the file system or if you are using MS SQL 2008 or higher take advantage of the new FILESTREAM type. 理想的解决方案是将文件存储在文件系统上,或者如果您使用的是MS SQL 2008或更高版本,请利用新的FILESTREAM类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM