无法在pdf生成中访问封闭流

时间:2015-12-01 16:30:25

标签: c# asp.net itextsharp

当我尝试使用带有多个表的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);

这是我的asp.net应用程序中的完整堆栈跟踪:

  

[ObjectDisposedException:无法访问已关闭的流。]
  System.IO .__ Error.StreamIsClosed()+57
  System.IO.MemoryStream.Write(Byte []缓冲区,Int32偏移量,Int32计数)   +11011171 iTextSharp.text.pdf.OutputStreamCounter.Write(Byte [] buffer,Int32 offset,Int32 count)+52
  iTextSharp.text.pdf.PdfIndirectObject.WriteTo(Stream os)+53
  iTextSharp.text.pdf.PdfBody.Write(PdfIndirectObject indirect,Int32   refNumber,Int32代)+100
  iTextSharp.text.pdf.PdfBody.Add(PdfObject objecta,Int32 refNumber,   Int32代,布尔inObjStm)+385
  iTextSharp.text.pdf.PdfWriter.AddToBody(PdfObject objecta,   PdfIndirectReference refa)+51
  iTextSharp.text.pdf.Type1Font.WriteFont(PdfWriter writer,   PdfIndirectReference piref,Object [] parms)+317
  iTextSharp.text.pdf.FontDetails.WriteFont(PdfWriter writer)+296
  iTextSharp.text.pdf.PdfWriter.AddSharedObjectsToBody()+180
  iTextSharp.text.pdf.PdfWriter.Close()+86
  iTextSharp.text.DocWriter.Dispose()+10
  System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender,   EventArgs e)+51 System.Web.UI.Control.OnLoad(EventArgs e)+92
  System.Web.UI.Control.LoadRecursive()+54
  System.Web.UI.Page.ProcessRequestMain(布尔   includeStagesBeforeAsyncPoint,Boolean includeStagesAfterAsyncPoint)   772

bytes - 数组应该可以在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);

但我仍然得到同样的错误。

5 个答案:

答案 0 :(得分:14)

PdfWriter默认关闭流。只需在PdfWriter.GetInstance

之后添加以下行
    protected void onCreate(Bundle savedInstanceState) 
    {
 EditText etDateF,etDateT,etLocation,etFormNo,etVIN,etEngine,etName;
     Button btSearch;
     LinearLayout liBottom;
     static int iState = 0; // 1=complaint;2=failure 
     String[][] saData = null;
        super.onCreate(savedInstanceState);
        methods = new gtCommanMethods(this);
        tableMaster = new TableMaster(this);

        Display  display= ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        bConstants.SCR_WIDTH = display.getWidth(); 
        bConstants.SCR_HEIGHT = display.getHeight();

        LinearLayout liMain = new LinearLayout(this);
        liMain.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
        liMain.setOrientation(LinearLayout.VERTICAL);

        etDateF = new EditText(this);
        etDateT = new EditText(this);
        etLocation = new EditText(this);
        etFormNo = new EditText(this);
        etVIN = new EditText(this);
        etEngine = new EditText(this);
        etName = new EditText(this);

        etDateF.setLayoutParams(new LinearLayout.LayoutParams(150, LinearLayout.LayoutParams.WRAP_CONTENT));
        etDateT.setLayoutParams(new LinearLayout.LayoutParams(150, LinearLayout.LayoutParams.WRAP_CONTENT));
        etLocation.setLayoutParams(new LinearLayout.LayoutParams(150, LinearLayout.LayoutParams.WRAP_CONTENT));
        etFormNo.setLayoutParams(new LinearLayout.LayoutParams(150, LinearLayout.LayoutParams.WRAP_CONTENT));
        etVIN.setLayoutParams(new LinearLayout.LayoutParams(150, LinearLayout.LayoutParams.WRAP_CONTENT));
        etEngine.setLayoutParams(new LinearLayout.LayoutParams(150, LinearLayout.LayoutParams.WRAP_CONTENT));
        etName.setLayoutParams(new LinearLayout.LayoutParams(150, LinearLayout.LayoutParams.WRAP_CONTENT));
        String search = getResources().getString(R.string.search);
        btSearch = new Button(this);
        btSearch.setText(search);
        btSearch.setBackgroundResource(R.drawable.green_patch);



        LinearLayout li1 = new LinearLayout(this);
        li1.setOrientation(LinearLayout.HORIZONTAL);
        li1.addView(new custText(this, getResources().getString(R.string.from_date)));
        li1.addView(etDateF);
        li1.addView(new custText(this, getResources().getString(R.string.to_date)));
        li1.addView(etDateT);

        LinearLayout li3 = new LinearLayout(this);
        li3.setOrientation(LinearLayout.HORIZONTAL);
        li3.addView(new custText(this, getResources().getString(R.string.location)));
        li3.addView(etLocation);

        if(iState == 1)
            li3.addView(new custText(this, getResources().getString(R.string.complaint_no)));
        else if(iState == 2)
            li3.addView(new custText(this, getResources().getString(R.string.failure_no)));

        li3.addView(etFormNo);

        LinearLayout li5 = new LinearLayout(this);
        li5.setOrientation(LinearLayout.HORIZONTAL);
        li5.addView(new custText(this, getResources().getString(R.string.vin)));
        li5.addView(etVIN);
        li5.addView(new custText(this, getResources().getString(R.string.eng_no)));
        li5.addView(etEngine);

        LinearLayout li7 = new LinearLayout(this);
        li7.setOrientation(LinearLayout.HORIZONTAL);
        li7.addView(new custText(this, getResources().getString(R.string.name)));
        li7.addView(etName);
        li7.addView(btSearch);

        LinearLayout liUpper = new LinearLayout(this);
        liUpper.setOrientation(LinearLayout.VERTICAL);

        liUpper.addView(li1);
        liUpper.addView(li3);
        liUpper.addView(li5);
        liUpper.addView(li7);

        liBottom = new LinearLayout(this);
        liBottom.setOrientation(LinearLayout.VERTICAL);

        LinearLayout liTableHeader = new LinearLayout(this);
        liTableHeader.setOrientation(LinearLayout.HORIZONTAL);
        liTableHeader.setBackgroundColor(Color.LTGRAY);
        liTableHeader.setPadding(0, 5, 0, 5);


        liTableHeader.addView(new custText(this,getResources().getString(R.string.name),true),new LinearLayout.LayoutParams(bConstants.SCR_WIDTH/3, LinearLayout.LayoutParams.WRAP_CONTENT));
        liTableHeader.addView(new custText(this, getResources().getString(R.string.phone_no),true),new LinearLayout.LayoutParams(bConstants.SCR_WIDTH/3, LinearLayout.LayoutParams.WRAP_CONTENT));
        liTableHeader.addView(new custText(this, getResources().getString(R.string.frame_vin_no),true),new LinearLayout.LayoutParams(bConstants.SCR_WIDTH/3, LinearLayout.LayoutParams.WRAP_CONTENT));


        liMain.addView(liUpper,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));

        liMain.addView(liTableHeader,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
        liMain.addView(liBottom,new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
        setContentView(liMain);}

答案 1 :(得分:1)

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

foreach (TableObject to in myTables.ToList())
{
     //some code stuff
This answer下的

this question帮助我解决了这个问题。

答案 2 :(得分:0)

using PdfWriter writer..阻止ms阻止基础流writer尝试处置PdfWriter writer的可能性。

尝试在没有using阻止的情况下使用getch删除并查看。它应该解决这个问题。

答案 3 :(得分:0)

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

ParseQuery<Article> query = new ParseQuery<Article>();

        if (souCategorie.SelectedIndex >= 0)
        {
            query.WhereEqualTo("idSCategorie", listeSouCategorie.ElementAt(souCategorie.SelectedIndex));
        }
        if(motcle.Text.Length > 0)
        {
            query.WhereContains("nom", motcle.Text);
           // query.WhereContains("description", motcle.Text);
        }
        if(distance.Text.Length>0)
        if (Convert.ToDouble(distance.Text) > 0)
        {
                Debug.WriteLine(distance.Text);
                ParseGeoPoint geo = new ParseGeoPoint();
            geo.Latitude = geoposition.Coordinate.Latitude;
            geo.Longitude = geoposition.Coordinate.Longitude;
            query.WhereWithinDistance("coordonnees", geo, ParseGeoDistance.FromKilometers(Convert.ToDouble(distance.Text)));
        }

        IEnumerable<Article> lst = await query.FindAsync();
        rechercheResult.DataContext = lst.ToList();

答案 4 :(得分:0)

该问题似乎是由于在关闭文档之前已处置PdfWriter。在PdfWriter的using语句中调用doc.Close()应该可以解决问题。