如何返回MemoryStream docx文件MVC?

时间:2013-01-31 16:20:06

标签: c# asp.net-mvc asp.net-mvc-3 file-upload docx

我有一个docx文件,我想在编辑后返回。我有以下代码......

object useFile = Server.MapPath("~/Documents/File.docx");
object saveFile = Server.MapPath("~/Documents/savedFile.docx");
MemoryStream newDoc = repo.ChangeFile(useFile, saveFile);
return File(newDoc.GetBuffer().ToArray(), "application/docx", Server.UrlEncode("NewFile.docx"));

该文件似乎很好,但我收到错误消息(“文件已损坏”,另一条说“Word发现不可读的内容。如果您信任源,请单击是”)。有什么想法吗?

提前致谢

修改

这是我模型中的ChangeFile ......

    public MemoryStream ChangeFile(object useFile, object saveFile)
    {
        byte[] byteArray = File.ReadAllBytes(useFile.ToString());
        using (MemoryStream ms = new MemoryStream())
        {
            ms.Write(byteArray, 0, (int)byteArray.Length);
            using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(ms, true))
            {                    
                string documentText;
                using (StreamReader reader = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
                {
                    documentText = reader.ReadToEnd();
                }

                documentText = documentText.Replace("##date##", DateTime.Today.ToShortDateString());
                using (StreamWriter writer = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
                {
                    writer.Write(documentText);
                }
            }
            File.WriteAllBytes(saveFile.ToString(), ms.ToArray());
            return ms;
        }
    }

2 个答案:

答案 0 :(得分:13)

我使用FileStreamResult

var cd = new System.Net.Mime.ContentDisposition
    {
        FileName = fileName,

        // always prompt the user for downloading, set to true if you want 
        // the browser to try to show the file inline
        Inline = false,
    };
Response.AppendHeader("Content-Disposition", cd.ToString());

return new FileStreamResult(documentStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");

答案 1 :(得分:9)

请勿使用MemoryStream.GetBuffer().ToArray()使用MemoryStream.ToArray()

GetBuffer()的原因与用于创建内存流的数组有关,而与内存流中的实际数据无关。底层阵列的大小实际上可能不同。

隐藏在MSDN上:

  

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