0

PDFを編集してから、新しいタブで印刷しています。「閉じたストリームにアクセスできません」というエラーが表示されます。これは私がこれまでに持っているものです...

コントローラ

public ActionResult QST(string ID) 
{   
    ...
    PdfReader reader = new PdfReader(Server.MapPath("~/Content/PDF/QST.pdf"));
    QstRepository repo = new QstRepository();
    Stream newPdf = repo.GS(ID, reader);            
    return new FileStreamResult(newPdf, "application/pdf");
}

モデル

public Stream GS(string ID, PdfReader reader)
{
    Stream newPdf = new MemoryStream();
    using (MemoryStream ms = new MemoryStream())
    {
        PdfStamper formFiller = new PdfStamper(reader, ms);
        AcroFields formFields = formFiller.AcroFields;
        formFields.SetField("ID", ID);

        formFiller.FormFlattening = true;
        formFiller.Writer.CloseStream = false;
        newPdf = ms;
        formFiller.Close();
    }
    return newPdf;
}

閉じる前に PDF にアクセスするにはどうすればよいですか... または、後で PDF にアクセスするにはどうすればよいですか?

4

2 に答える 2

3

戻る前のコードの最後の 2 行は次のとおりです。

newPdf = ms;
formFiller.Close(); 

コードはすべてusing (MemoryStream ms = new MemoryStream())ブロック内にあるため、MemoryStreamとにかく戻る前に ms が閉じられます。

newPdf変数に代入しているためms、nwePdf は最終的に同じ (既に閉じられている)MemoryStreamを返しますms

using ブロックを使用せずにストリームを作成することもできますpublic Stream GS(string ID, PdfReader reader)が、コードで例外が発生した場合にストリームが開いたままになるリスクがあります。次のことを試すことができると思います。

// All calls to GS() must ensure that the returned stream gets closed.
public Stream GS(string ID, PdfReader reader) 
{ 
    MemoryStream newPdf = new MemoryStream();
    PdfStamper formFiller = null;
    try 
    { 
        formFiller = new PdfStamper(reader, newPdf); 
        AcroFields formFields = formFiller.AcroFields; 
        formFields.SetField("ID", ID); 

        formFiller.FormFlattening = true;
        //formFiller.Writer.CloseStream = false;
    }
    catch
    {
        // Only close newPdf on an exception
        newPdf.Close();
        throw; // Rethrow original exception
    }
    finally
    {
        // Always ensure that formFiller gets closed
        formFiller.Close();
    }
    return newPdf; 
} 

更新:余分な MemoryStream を削除しました。これは、関数の先頭で単純に宣言され、最後に他のものを指すように設定されていたため、その間に他の目的で使用されることはありませんでした。

更新: PdfStamper を使用した例を見つけました。例によると、実際にストリームに書き込むのは formFiller.Close() の呼び出しです。彼らの例では、Writer.CloseStream プロパティを false に設定していません。そのため、空白のページが表示される可能性があります。残念ながら、これを確認するための PdfStamper に関する実際のドキュメントを見つけることができませんでした。

于 2012-06-07T18:59:32.090 に答える
1

コード内で、同じインスタンスmsを参照します。はブロックの最後で閉じられているため、(同じストリームであるため) も閉じられています。したがって、閉じずに返す必要があります。newPdfMemoryStreammsusingnewPdfStream

public Stream GS(string ID, PdfReader reader)
{
    PdfStamper formFiller = new PdfStamper(reader, ms);
    AcroFields formFields = formFiller.AcroFields;
    formFields.SetField("ID", ID);

    formFiller.FormFlattening = true;
    formFiller.Writer.CloseStream = false;
    formFiller.Close();
    return ms;
}

私は ASP.NET MVC にあまり詳しくありませんがFileStreamResult、ストリームを閉じる処理はそれで済むと思います。

于 2012-06-07T19:00:28.343 に答える