21

その場で作成したWord文書をブラウザにストリーミングできません。Microsoft Wordから、ドキュメントが破損しているというメッセージが常に表示されます。

コンソールアプリケーションを介してコードを実行し、ASP.NETを画像から削除すると、ドキュメントは問題なく正しく生成されます。私はすべてがファイルを書き留めることに集中していると信じています。

これが私のコードです:

using (MemoryStream mem = new MemoryStream())
{
    // Create Document
    using (WordprocessingDocument wordDocument = WordprocessingDocument.Create(mem, WordprocessingDocumentType.Document, true))
    {
        // Add a main document part. 
        MainDocumentPart mainPart = wordDocument.AddMainDocumentPart();

        new Document(new Body()).Save(mainPart);

        Body body = mainPart.Document.Body;
        body.Append(new Paragraph(new Run(new Text("Hello World!"))));

        mainPart.Document.Save();
        // Stream it down to the browser

        // THIS IS PROBABLY THE CRUX OF THE MATTER <---
        Response.AppendHeader("Content-Disposition", "attachment;filename=HelloWorld.docx");
        Response.ContentType = "application/vnd.ms-word.document";
        mem.WriteTo(Response.OutputStream);
        Response.End();
    }
}

私はたくさんのリンクをてきましたが、何もうまくいきません。私は多くの人が使用し、一部の人は使用しています–現時点では、正しい方法がわかりません。また、私はより長いコンテンツタイプを試しましたが、運がありません。MemoryStream.WriteToBinaryWriteapplication/vnd.openxmlformats-officedocument.wordprocessingml.document

一部のスクリーンショット–回復しようとしても、同じ「パーツが欠落しているか無効」になります

この質問につまずいた人のための解決策:

usingのディレクティブ内でWordProcessingDocument、次を呼び出す必要があります。

wordDocument.Save();

また、を正しくストリーミングするMemoryStreamには、これを外側のusingブロックで使用します。

Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
Response.AppendHeader("Content-Disposition", "attachment;filename=HelloWorld.docx");
mem.Position = 0;
mem.CopyTo(Response.OutputStream);
Response.Flush();
Response.End();

ここに画像の説明を入力してください ここに画像の説明を入力してください

4

7 に答える 7

8

代わりに、ターゲットストリームが一度にすべてを書き込むことをサポートしていない場合に、バッファのコンテンツ全体を書き込めないCopyToというバグがあります。WriteTo

于 2012-05-19T19:51:34.997 に答える
3

.NETFramework3.5以下のバリアントとして。このバージョンのフレームワークにはCopyTo、クラスのメソッドがありませんStream。したがって、メソッドWriteToは次のコードに置き換えられます。

byte[] arr = documentStream.ToArray();
fileStream.Write(arr, 0, arr.Length);

例はhttp://blogs.msdn.com/b/mcsuksoldev/archive/2010/04/09/creating-a-new-microsoft-word-document-from-a-template-using-openxml.aspxによって見つかりました

于 2013-09-26T09:30:09.523 に答える
2

コードをコピーして貼り付けたところ、: "wordDocument.close();"であることがわかりました。clausuleが欠落していて、追加して機能しました(Asp.NET MVCでアクションを実行しました)

于 2013-02-19T17:48:45.033 に答える
2

ContentTypeの値が正しくないと思います。これはWord97-2003形式用です。次のように変更します。

application/vnd.openxmlformats-officedocument.wordprocessingml.document

それで問題が解決するかどうかを確認します。

于 2012-05-19T21:27:10.527 に答える
2

(これはOpenXML SDKv2.10.0および.NetCorev2.2を使用しています)

私はこれが答えられたことを知っていますが、私は別の選択肢を捨てたかったのです。以下のようにFile()でストリームを送り返そうとすると、ドキュメントが破損するのは正しいことです。

                MemoryStream updateStream = new MemoryStream();
                wordDocument.Save();
                wordDocument.Clone(updateStream);


                return File(updateStream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");

`

非常に単純な代替/回避策は、ストリームを以下のようにbyte []に​​変換することであり、これにより、有効なワードdocxが生成されます。

                MemoryStream updateStream = new MemoryStream();
                wordDocument.Save();
                wordDocument.Clone(updateStream);


                return File(updateStream.ToArray(), "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
于 2020-01-16T03:24:17.677 に答える
0

ロディオンの答えを拡張し、質問で使用された変数と一致させるために、これは私のために働いたものです:

Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
Response.AppendHeader("Content-Disposition", "attachment;filename=HelloWorld.docx");
mem.Position = 0;
byte[] arr = mem.ToArray();
Response.BinaryWrite(arr);
Response.Flush();
Response.End();
于 2015-07-20T18:21:53.260 に答える
0

まず、常にContent-Lengthを含めます。ブラウザがhttp応答本文の長さを認識していない場合、接続は開いたままになります(維持)。他に方法がない場合は、コンテンツを一時ファイルに保存し(閉じるときに削除オプションを使用)、コンテンツの長さを取得します。

次に、ドキュメント処理IN-MEMは、すべてのオプションで機能するわけではありません(たとえば、ドキュメントにチャンクを挿入することはできません。ファイルモードを使用する必要があります)。

以下は、aspnetコアのサンプルです。

[HttpPost]
public async Task<ActionResult<MopedResponse>> PostAsync(IFormCollection collection)
{

    string pathTemp = Path.GetTempFileName(); // get the temp file name

    // create or process the word file

    // reopen it for serving

    FileStream merged = new FileStream(pathTemp, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);

    System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
    {
        FileName = "parafa.docx",
        Inline = true  // false = prompt the user for downloading;  true = browser to try to show the file inline
    };
    Response.Headers.Add("Content-Disposition", cd.ToString());
    Response.Headers.Add("Content-Length", merged.Length.ToString());

    return File(merged, "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "mywordFile1.docx");

}
于 2018-12-03T09:35:56.803 に答える