asp.net 无法 访问 pdf 生成 中 的 已 关闭 流

vshtjzan  于 2022-11-19  发布在  .NET
关注(0)|答案(6)|浏览(229)

当我尝试使用iTextSharp构建包含多个表格的PDF文件时,收到以下错误消息:
无法访问已关闭的流。
下面是我的代码:

//Create a byte array that will eventually hold our final PDF
Byte[] bytes;

List<TableObject> myTables = getTables();
TableObject currentTable = new TableObject();

//Boilerplate iTextSharp setup here
//Create a stream that we can write to, in this case a MemoryStream
using (MemoryStream ms = new MemoryStream())
{
    //Create an iTextSharp Document which is an abstraction of a PDF but **NOT** a PDF
    using (Document doc = new Document(PageSize.A4, 10f, 10f, 10f, 0f))
    {
        foreach (TableObject to in myTables)
        {
            //Create a writer that's bound to our PDF abstraction and our stream
            using (PdfWriter writer = PdfWriter.GetInstance(doc, ms))
            {
                if (!doc.IsOpen())
                {
                    //Open the document for writing
                    doc.Open();
                }
                //Get the data from database corresponding to the current tableobject and fill all the stuff we need!
                DataTable dt = getDTFromID(to._tableID);
                Object[] genObjects = new Object[5];
                genObjects = gen.generateTable(dt, currentTable._tableName, currentTable._tableID.ToString(), currentTable, true);

                StringBuilder sb = (StringBuilder)genObjects[1];
                String tableName = sb.ToString();
                Table myGenTable = (Table)genObjects[0];
                String table = genObjects[2].ToString();

                using (StringReader srHtml = new StringReader(table))
                {
                    //Parse the HTMLiTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
                }

                //should give empty page at the end, need to fix it later
                doc.NewPage();
            }

        }
        doc.Close();
    }

    //After all of the PDF "stuff" above is done and closed but **before** we
    //close the MemoryStream, grab all of the active bytes from the stream
    bytes = ms.ToArray();
}

//Now we just need to do something with those bytes.
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=Report_complete.pdf");
Response.BinaryWrite(bytes);

下面是我的www.example.com应用程序的完整堆栈跟踪asp.net:
[对象处理异常:无法访问已关闭的流。]
系统. IO.__错误.数据流关闭()+57
系统.IO.内存流.写入(字节[]缓冲区,Int 32偏移量,Int 32计数)+11011171 iTextSharp.文本.pdf.输出流计数器.写入(字节[]缓冲区,Int 32偏移量,Int 32计数)+52
翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:翻译:
(间接对象,整数32参考编号,整数32生成)+100
添加(PdfObject对象,Int 32引用编号,Int 32生成,对象中的布尔值)+385
添加到正文(PdfObject对象,PdfIndirectReference引用)+51
+317(数据写入器写入器,数据间接引用指针,对象[]参数)
+296,请输入您要的字体。
中文字幕翻译:中文字幕翻译:中文字幕翻译:中文字幕翻译:中文字幕翻译:中文字幕翻译:
联系我们联系方式+86
文件处理器()+10
+51系统. Web.UI.控件.OnLoad(事件参数e)+92
系统.Web.UI.控件.加载递归()+54
系统.Web.UI.页面.处理请求主页面(布尔值包括异步点之前的阶段,布尔值包括异步点之后的阶段)+772
bytes-Array应该可以在using语句中访问,但似乎存在错误。
我试过将foreach循环移到using(writer ...)块中:

//Create a byte array that will eventually hold our final PDF
//must be outside of the foreach loop (and everything else), because we store every single generated table in here for the final pdf!!
Byte[] bytes;

List<TableObject> myTables = getTables();
TableObject currentTable = new TableObject();

//Boilerplate iTextSharp setup here
//Create a stream that we can write to, in this case a MemoryStream
using (MemoryStream ms = new MemoryStream())
{
    //Create an iTextSharp Document which is an abstraction of a PDF but **NOT** a PDF
    using (Document doc = new Document(PageSize.A4, 10f, 10f, 10f, 0f))
    {
            //Create a writer that's bound to our PDF abstraction and our stream
            using (PdfWriter writer = PdfWriter.GetInstance(doc, ms))
            {
                //loop all tableobjects inside the document & the instance of PDFWriter itself! 
                foreach (TableObject to in myTables)
                {
                    //only happens on the first run!
                    if (!doc.IsOpen())
                    {
                        //Open the document for writing
                        doc.Open();
                    }
                    //Get the data from database corresponding to the current tableobject and fill all the stuff we need!
                    DataTable dt = getDTFromID(to._tableID);
                    Object[] genObjects = new Object[5];
                    genObjects = gen.generateTable(dt, currentTable._tableName, currentTable._tableID.ToString(), currentTable, true);

                    StringBuilder sb = (StringBuilder)genObjects[1];
                    String tableName = sb.ToString();
                    Table myGenTable = (Table)genObjects[0];
                    String table = genObjects[2].ToString();

                    using (StringReader srHtml = new StringReader(table))
                    {
                        //Parse the HTML
                        iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
                    }

                    //this will probably render a whole new page at the end of the file!! need to be fixed later!!!
                    doc.NewPage();
                }
                //After all of the PDF "stuff" above is done and closed but **before** we
                //close the MemoryStream, grab all of the active bytes from the stream
                bytes = ms.ToArray();
            }
        doc.Close();
    }

}

//Now we just need to do something with those bytes.
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=ShiftReport_complete.pdf");
Response.BinaryWrite(bytes);

但我还是得到同样的错误。

kpbpu008

kpbpu0081#

默认情况下,PdfWriter关闭流。

writer.CloseStream = false;
vfhzx4xs

vfhzx4xs2#

PdfWriter writer..上的using区块在尝试处置writer时,可能会关闭基础数据流ms
尝试使用不带using块的PdfWriter writer进行删除,然后参阅。这样应该可以解决问题。

laik7k3q

laik7k3q3#

using命令会导致释放MemoryStream,因此在您访问它时,托管和非托管资源已经被释放。将以下代码放在foreach循环的右括号之后:

bytes = ms.ToArray();
nbnkbykc

nbnkbykc4#

解决方案很简单,只需将.ToList()放入foreach循环中的集合:

foreach (TableObject to in myTables.ToList())
{
     //some code stuff

this question下的This answer帮助我解决了这个问题。

rxztt3cl

rxztt3cl5#

当我有一个没有行的空表时,我用xmlworker(iTextSharp html到pdf)得到**“无法访问关闭的流”**:

<table>
    @if (false) 
    {
       <tr>
           <td>Foo</td>
       </tr>
    }
 </table>
dgenwo3n

dgenwo3n6#

此问题似乎是由于在关闭文档之前释放了PdfWriter所致。在PdfWriter的using语句内调用doc.Close()应该可以解决此问题。

相关问题