closed Stream.解決辦法


假設有這麼一段代碼:
         private   void  CreatePdf()
        
{
            Document doc
=new Document();
            MemoryStream ms
=new MemoryStream();
            PdfWriter writer 
=PdfWriter.GetInstance(doc,ms);
            doc.Open();
            doc.Add(
new Paragraph(DateTime.Now.ToLongDateString()));
            doc.Close();
            ViewPdf(ms);
        }


        
private   void  ViewPdf(Stream fs)
        
{
            
byte[] buffer=new byte[fs.Length];
            fs.Position
=0;            
            fs.Read(buffer,
0,(int)fs.Length);
            Response.Clear();
            Response.ContentType 
= "application/pdf";
            Response.BinaryWrite(buffer);
            Response.OutputStream.Flush();
            Response.OutputStream.Close();
        }

在調用CreatePdf()的時候碰到了以下錯誤:

Cannot access a closed Stream.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ObjectDisposedException: Cannot access a closed Stream.

Source Error:

Line 58:   private void ViewPdf(Stream fs)

            Line 59:   {

            Line 60: byte[] buffer=new byte[fs.Length]; Line 61:    fs.Position=0;

            Line 62:    fs.Read(buffer,0,(int)fs.Length);

問題出在哪裏了呢?從錯誤我能夠知道咱們準備操做的Stream已經關閉,這是由於iTextSharp自動關閉生成的Stream了,那有沒有辦法不關閉呢?
看了下面這段代碼,也許就不用我說什麼了:
     private   void  Page_Load( object  sender, System.EventArgs e)
        
{
            
//CreatePdf();
            EditPDF();
        }


        
private   void  EditPDF()
        
{
            PdfReader reader 
=new PdfReader(@"e:\xml2PDF.pdf");
            MemoryStream ms
=new MemoryStream();
            PdfStamper stamper
=new PdfStamper(reader,ms);
            stamper.Writer.CloseStream
=false;
            PdfContentByte cb
=stamper.GetOverContent(1);            
            cb.Circle(
250,250,50);
            cb.SetColorFill(iTextSharp.text.Color.RED);
            cb.SetColorStroke(iTextSharp.text.Color.WHITE);
            cb.FillStroke();
            stamper.Close();
            ViewPdf(ms);        
        }


        
private   void  CreatePdf()
        
{
            Document doc
=new Document();
            MemoryStream ms
=new MemoryStream();
            PdfWriter writer 
=PdfWriter.GetInstance(doc,ms);
            writer.CloseStream
=false;
            doc.Open();
            doc.Add(
new Paragraph(DateTime.Now.ToLongDateString()));
            doc.Close();
            ViewPdf(ms);
        }


        
private   void  ViewPdf(Stream fs)
        
{
            
byte[] buffer=new byte[fs.Length];
            fs.Position
=0;            
            fs.Read(buffer,
0,(int)fs.Length);
            fs.Close();
            Response.Clear();
            Response.ContentType 
= "application/pdf";
            Response.BinaryWrite(buffer);
            Response.OutputStream.Flush();
            Response.OutputStream.Close();
        }

原來PdfWriter有個熟悉就是讓咱們設置是否自動關閉Stream的,而默認是關閉的。

2006-12-01更新ViewPdf function
         private   void  ViewPdf(Stream fs)
        {
            
byte [] buffer  =   new   byte [fs.Length];
            fs.Position 
=   0 ;
            fs.Read(buffer, 
0 , ( int )fs.Length);
            Response.Clear();
            
// Response.AddHeader("Content-Disposition", "attachment;FileName=out.pdf");
            Response.AddHeader( " Content-Length " ,fs.Length.ToString()); 
            Response.ContentType 
=   " application/pdf " ;
            fs.Close();

            Response.BinaryWrite(buffer);
            Response.OutputStream.Flush();
            Response.OutputStream.Close();
        } 
若是須要下載而不是在IE中看的話,請把Response.AddHeader("Content-Disposition", "attachment;FileName=out.pdf");前的註釋去掉,並替換上你想要的名字。

若是不指定 Response.AddHeader( " Content-Length " ,fs.Length.ToString());,IE會把網頁內容也輸出,在PDF後面,此時顯示生成的PDF被破壞(這個說是IE的一個bug,我也不清楚)
若是附件名爲中文:
Response.AddHeader("Content-Disposition", "attachment;FileName="+HttpUtility.UrlEncode("中文.pdf"));

內嵌顯示PDF
Response.AddHeader("Content-Disposition", "inline;FileName=out.pdf");

更多這方面的信息google上搜索吧。

另一個和緩存有關的信息,Cache-Control,須要的本身研究下吧。

posted on 2006-02-23 17:36 RubyPDF 閱讀(10570) 評論( 37) 編輯 收藏

FeedBack:
2006-02-23 23:31 | bincoding[未註冊用戶]
請教:要利用Adobe Reader 的dll嗎?若是是的,又是引用的哪一個dll?
  
#2樓 [ 樓主]
2006-02-24 07:39 | HardRock  
客戶端若是正常安裝(會自動安裝瀏覽器插件)了acrobat或者acrobat reader,便可以看輸出的PDF,若是沒有,生成的PDF文件會提示下載。
  
2006-12-01 11:07 | 多多[匿名][未註冊用戶]
爲何個人itextsharp1.4裏的PdfWriter 沒有CloseStream屬性?
writer.CloseStream=false; 顯示找不到這個屬性
  
#4樓 [ 樓主]
2006-12-01 11:15 | HardRock  
@多多[匿名]
你說的是iTextSharp 3.1.4仍是iText的1.4?
iTextSharp裏不會沒有這個屬性的,你本身看下iTextSharp的源代碼吧。
  
2006-12-01 13:28 | 多多[匿名][未註冊用戶]
下載了最新版的itextsharp,有這個屬性,但用了上面的方法後仍是顯示空白頁面,並且對於有圖片的多頁pdf還顯示「文件已被損壞,並且沒法修復」,我用的是asp.net2.0和acrobat6.0,代碼以下:
protected void Page_Load(object sender, EventArgs e)
{
iTextSharp.text.Rectangle pageSize = PageSize.A4;
pageSize.BackgroundColor = new iTextSharp.text.Color(0xFF, 0xFF, 0xDE);

MemoryStream m = new MemoryStream();
Document document = new Document(pageSize);



PdfWriter writer = PdfWriter.GetInstance(document, m);
writer.CloseStream = false;
document.Open();
document.Add(new Paragraph(DateTime.Now.ToString()));
document.NewPage();
document.Add(new Paragraph("Hello World"));

document.Close();
//writer.Flush();
ViewPdf(m);

}
private void ViewPdf(Stream fs)
{
byte[] buffer = new byte[fs.Length];
fs.Position = 0;
fs.Read(buffer, 0, (int)fs.Length);
fs.Close();
Response.Clear();
Response.ContentType = "application/pdf";
Response.BinaryWrite(buffer);
Response.OutputStream.Flush();
Response.OutputStream.Close();
}
  
#6樓 [ 樓主]
2006-12-01 14:10 | HardRock  
@多多[匿名]
這個是個人方法中的bug,很差意思。
上面已經作了更新,並介紹了更多相關信息,本身看吧
  
2006-12-01 14:38 | 多多[匿名][未註冊用戶]
更新的真快呀,問題解決了。謝謝你。
  
#8樓 [ 樓主]
2006-12-01 14:42 | HardRock  
@多多[匿名]
不客氣,歡迎多來光顧,併到個人新網站捧場
http://www.rubypdf.com
  
2007-01-24 17:23 | xiaocai[未註冊用戶]
iTextSharp.text.Document document = new iTextSharp.text.Document(PageSize.A4, 10, 10, 10, 10);
MemoryStream ms = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(document, ms);
writer.CloseStream = false;
try
{
document.Open();
iTextSharp.text.Table dt = new iTextSharp.text.Table(5); ;
float[] headerwidths = { 200, 100, 100, 100, 100 };
dt.Widths = headerwidths;
BaseFont bfHei = BaseFont.CreateFont(@"C:\WINDOWS\Fonts\SIMYOU.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
Color Test = new Color(255, 255, 255);

Font font = new Font(bfHei, 10, 1, Test);
Font font1 = new Font(bfHei, 10);
document.Add(new Paragraph(" 公司:xx", font1));
document.Add(new Paragraph(" 說明:" + txtDatetime.Text + "號的網站流量分析", font1));
document.Add(new Paragraph(" 生成時間:" + DateTime.Now.ToString(), font1));

Cell cell = new Cell(new Phrase("時間 ", font));
cell.Rowspan = 2;
cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.VerticalAlignment = Element.ALIGN_MIDDLE;
cell.BackgroundColor = new Color(100, 125, 150);
dt.AddCell(cell);
document.Add(dt);
document.Close();
ViewPdf(ms);

}
catch (DocumentException de)
{
Console.Error.WriteLine(de.Message);
}
catch (IOException ioe)
{
Console.Error.WriteLine(ioe.Message);
}


}

private void ViewPdf(Stream fs)
{
byte[] buffer = new byte[fs.Length];
fs.Position = 0;
fs.Read(buffer, 0, (int)fs.Length);
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment;FileName=Example.pdf");
Response.AddHeader("Content-Length", fs.Length.ToString());
Response.ContentType = "application/pdf";
fs.Close();

Response.BinaryWrite(buffer);
Response.OutputStream.Flush();
Response.OutputStream.Close();
}


這段代碼爲何會出錯,能不能幫我講解一下!!
  
#10樓 [ 樓主]
2007-01-24 17:38 | HardRock  
@xiaocai
能把報錯也貼出來嗎?這樣我也少花點時間。
  
2007-01-24 17:58 | xiaocai[未註冊用戶]
索引超出範圍。必須爲非負值並小於集合大小。
參數名: index
說明: 執行當前 Web 請求期間,出現未處理的異常。請檢查堆棧跟蹤信息,以瞭解有關該錯誤以及代碼中致使錯誤的出處的詳細信息。

異常詳細信息: System.ArgumentOutOfRangeException: 索引超出範圍。必須爲非負值並小於集合大小。
參數名: index

源錯誤:


行 43: cell.BackgroundColor = new Color(100, 125, 150);
行 44: dt.AddCell(cell);
行 45: document.Add(dt);
行 46: document.Close();
行 47: ViewPdf(ms);

--------
就是這個出錯,我使用的是最新的itextsharp-3[1].1.8-dll,之前使用的版本很低,可是我要直接輸出流,而不是生成Pdf文件,因此換成更新的版本纔有writer.CloseStream這個屬性,請幫幫看看,謝謝!
  
#12樓 [ 樓主]
2007-01-24 18:04 | HardRock  
你沒有弄明白怎麼使用Table,請查看相關例子,個人教程中有相關例子

你把Table設置爲5列,結果你只添加了一列,這樣固然不行的,你看下我給你改的代碼,不知道這是否是你想要的。

protected void Page_Load(object sender, EventArgs e)
{
iTextSharp.text.Document document = new iTextSharp.text.Document(PageSize.A4, 10, 10, 10, 10);
MemoryStream ms = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(document, ms);
writer.CloseStream = false;
try
{
document.Open();
iTextSharp.text.Table dt = new iTextSharp.text.Table(5); ;
float[] headerwidths = { 200, 100, 100, 100, 100 };
dt.Widths = headerwidths;
BaseFont bfHei = BaseFont.CreateFont(@"C:\\WINDOWS\\Fonts\\SIMYOU.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
Color Test = new Color(255, 255, 255);

Font font = new Font(bfHei, 10, 1, Test);
Font font1 = new Font(bfHei, 10);
dt.AddCell(new Cell(new Paragraph(" 公司:xx", font1)));
dt.AddCell(new Cell(new Paragraph(" 說明:" + txtDatetime.Text + "號的網站流量分析", font1)));
dt.AddCell(new Cell(new Paragraph(" 生成時間:" + DateTime.Now.ToString(), font1)));

Cell cell = new Cell(new Phrase("時間 ", font));
cell.Colspan = 2;

cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.VerticalAlignment = Element.ALIGN_MIDDLE;
cell.BackgroundColor = new Color(100, 125, 150);
dt.AddCell(cell);

document.Add(dt);
document.Close();
ViewPdf(ms);

}
catch (DocumentException de)
{
Console.Error.WriteLine(de.Message);
}
catch (IOException ioe)
{
Console.Error.WriteLine(ioe.Message);
}
}

private void ViewPdf(Stream fs)
{
byte[] buffer = new byte[fs.Length];
fs.Position = 0;
fs.Read(buffer, 0, (int)fs.Length);
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment;FileName=Example.pdf");
Response.AddHeader("Content-Length", fs.Length.ToString());
Response.ContentType = "application/pdf";
fs.Close();

Response.BinaryWrite(buffer);
Response.OutputStream.Flush();
Response.OutputStream.Close();
}
  
2007-01-25 08:37 | xiaocai[未註冊用戶]
原來如此,謝謝了!
還有一個問題我以爲很奇怪,就是是Table的時候,寫進PDF,它的單元格高度好像不能設置,因此我把全部單元格都設置cell.Rowspan = 2;不過感受仍是過高了,問一下要怎麼設置,仍是固定不能改了!!
  
2007-01-25 09:17 | DHC[未註冊用戶]
@HardRock
你好!

在IE中內嵌顯示PDF
用PdfStamper中的JavaScript可否控制經過對話框打印並關閉窗口?
如今使用了PdfStamper.JavaScript = "this.print(true);"可讓PDF在IE中打開並彈出Print的設置對話框,如今若是我想點print對話框的Cancel按鈕,就 不打印並讓窗口關閉,Ok按鈕是打印並關閉窗口,能經過JavaScript控制嗎?
或者有其餘的方式能實現嗎?

謝謝高手了!
  
2007-01-25 09:24 | DHC[未註冊用戶]
@HardRock
你好!

在IE中內嵌顯示PDF
用PdfStamper中的JavaScript可否控制經過對話框打印並關閉窗口?
如今使用了PdfStamper.JavaScript = "this.print(true);"可讓PDF在IE中打開並彈出Print的設置對話框,如今若是我想點print對話框的Cancel按鈕,就 不打印並讓窗口關閉,Ok按鈕是打印並關閉窗口,能經過JavaScript控制嗎?
或者有其餘的方式能實現嗎?

謝謝高手了!
  
2007-01-25 11:43 | DHC[未註冊用戶]
@HardRock
你好!

我如今程序中是這樣寫的:

PdfStamper.JavaScript = "this.print(true);this.closeDoc();"

生成的PDF直接在IE中內嵌顯示,會彈出對話框,可是點了按鈕以後不會關閉.

若是用Adobe Reader 打開的話,能夠在點擊彈出的print對話框中ok或cancel按鈕後關閉文檔,但在IE中就沒法關閉.怎麼能在IE中也實現關閉呢?
  
#17樓 [ 樓主]
2007-01-25 12:51 | HardRock  
@DHC
很差意思,這個我也不清楚了,也許在IE裏就沒法關閉。
  
2007-01-25 14:13 | xiaocai[未註冊用戶]
pdf的table能設置單元格高度嗎!
  
2007-01-25 14:26 | DHC[未註冊用戶]
@HardRock

Thank u all the same!

這個方案想法比較好,可是基本上很難實現,如今正在尋求其餘的解決方法,由於在IE內嵌PDF,要作到只能打印,不能copy是不可能的.能在客 戶端瀏覽器中顯示,就能保存,因此只能從PDF自己來作,可是若是給PDF設定密碼,那對於操做的人若是不知道密碼,還打不開,雖然能預防copy出來的 文件被其餘人看見,但密碼的維護又是一個很頭疼的問題.無論怎麼說,仍是謝謝了!
  
#20樓 [ 樓主]
2007-01-25 14:39 | HardRock  
@DHC
是的,只要能打印,就已經被cache到本地了,另外密碼的安全性也是問題。
有些專業的插件是能夠作到只能在線瀏覽的,好比fileopen還有上海某公司作的一個產品,不過都比較貴。
我曾經研究過一個替代方案,不過已經扔到一邊好久了,至於效果如何,還不清楚呢。
  
#21樓 [ 樓主]
2007-01-25 14:40 | HardRock  
@xiaocai
table是否能夠我不知道,你能夠看下api嘛
pdfptable確定能夠的,是defaultcell.height吧,api中很詳細的,個人教程裏估計也有相關的實例的。
  
2007-01-25 15:01 | xiaocai[未註冊用戶]
@HardRock

謝謝提醒!
  
2007-01-26 16:42 | DHC[未註冊用戶]
@HardRock

高手大哥,我想問個問題,如今個人程序有一個地方很是影響整個程序的擴展性,

針對一個已經存在的PDF文檔,若是我只想給它設定密碼,用pdfStamper,我如今的作法本身以爲頗有問題

Dim reader As New PdfReader(oldPath)
Dim stamper As New PdfStamper(reader, _
New FileStream(newPath, _
FileMode.Create), reader.PdfVersion)

其中oldPath是原有文件,newPath是我新生成的文件(兩個路徑沒法指定相同,會有IOException)
這樣的話我就不是改變原有文件,而是另外生成一個文件了,怎麼樣能在原有文件上直接編輯呢?
  
#24樓 [ 樓主]
2007-01-26 18:06 | HardRock  
Stream s=File.Open("", FileMode.Open);
PdfReader reader=new PdfReader(s);
s.Close();

btw,
老大,把你的PDF活給我作吧,我也好賺點外快,否則我收你服務費也行。:)
  
2007-01-27 09:43 | DHC[未註冊用戶]
@HardRock

謝謝指點,我是新進社員,接觸程序不到一年,因此...多包涵.
高手一句話,真解決問題啊.

謝謝了
  
#26樓 [ 樓主]
2007-01-27 20:00 | HardRock  
@DHC
你不是日本人吧,好像中國人在公司裏不叫社員的,並且你也不是咱們公司的員工,哪裏來的新進一說呢。
謝謝你的恭維。
  
2007-02-05 20:53 | DHC[未註冊用戶]
@HardRock

去年剛進公司以前,看了一韓劇<新進社員>,很是激勵個人鬥志,推薦剛參加或即將參加工做的人看看:)

老大,能不能用stamper就把toolbar隱藏了?我好像沒找到方法,就只有用writer才能設定嗎?
  
2007-02-05 21:09 | DHC[未註冊用戶]
@HardRock

老大,我找到了:)
  
2007-03-21 09:55 | 凌雲[未註冊用戶]
一個很奇怪的問題
好不容易找到老大的代碼。卻遇到這樣的問題。代碼是這樣的
private void Button1_Click(object sender, System.EventArgs e)
{
this.CreatePdf();
}
private void CreatePdf()
{
Document doc=new Document();
MemoryStream ms=new MemoryStream();
PdfWriter writer =PdfWriter.GetInstance(doc,ms);
writer.CloseStream=false;
doc.Open();
doc.Add(new Paragraph(DateTime.Now.ToLongDateString()));
doc.Close();
ViewPdf(ms);
}

private void ViewPdf(Stream fs)
{
byte[] buffer = new byte[fs.Length];
fs.Position = 0;
fs.Read(buffer, 0, (int)fs.Length);
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment;FileName=out.pdf");

Response.ContentType = "application/pdf";
fs.Close();

Response.BinaryWrite(buffer);
Response.OutputStream.Flush();
Response.OutputStream.Close();
}

頁面上是這樣的
<TABLE width="100%">
<tr>
<td style="HEIGHT: 58px"> <asp:Button id="Button1" runat="server" Text="Button"></asp:Button></td>
</tr>
<tr>
<td style="HEIGHT: 58px"><asp:linkbutton id="LinkButton1" runat="server">LinkButton</asp:linkbutton></td>
</tr>
</TABLE>

我發現去掉linkbutton控件生成的PDF文件就能夠打開打開。可是一加上LinkButton控件打開PDF時就出現「當打開文檔時發生錯誤。文件已損壞而且沒法修復。」但願能給於指點,小妹不勝感激。
注:我用的是Adobe Acrobat 6.0
VS.NET 2003
  
#30樓 [ 樓主]
2007-03-21 10:05 | HardRock  
@凌雲
請看我上面已經更新的代碼。
  
2007-03-21 10:11 | 凌雲[未註冊用戶]
我用的就是你 2006-12-01更新ViewPdf function。 不過是
//Response.AddHeader("Content-Disposition", "attachment;FileName=out.pdf");
Response.AddHeader("Content-Length",fs.Length.ToString());

這兩行我改了一下 把第一個註釋去掉了 用第二個
  
2007-06-12 01:04 | eua@gmail.com[未註冊用戶]
???
  
2007-12-26 15:09 | szhlq[未註冊用戶]
我所有參照你2006-12-01更新ViewPdf function的代碼,只是把它移植到vb.net 2003 上,可是我只能當我選擇保存pdf 文件時,也就是把
//Response.AddHeader("Content-Disposition", "attachment;FileName=out.pdf"); 註釋去掉,我可以將pdf 保存在指定的位置,可是頁面 確不能顯示內容;
Action canceled
Internet Explorer was unable to link to the Web page you requested. The page might be temporarily unavailable.

請幫幫我,謝謝!
  
2009-02-17 10:21 | 執迷不悟  
Thanks!
明白了,看來我得去看看文件操做的原理了。
  
2009-02-18 11:06 | 執迷不悟  
改進的ViewPdf,IE會輸出HTML代碼是你沒控制程序的輸出,不是BUG。沒有作異常處理,應用的時候還得加上,但願對你們有幫助。 private void ViewPdf(Stream fs) { Response.Clear(); Response.AddHeader("Content-Disposition", "attachment;FileName=out.pdf"); //Response.AddHeader("Content-Length", fs.Length.ToString()); Response.ContentType = "application/pdf"; long fileLength = fs.Length; int size = 10240;//10K一塊下載 byte[] readData = new byte[size]; if (size > fileLength) size = Convert.ToInt32(fileLength); long fPos = 0; bool isEnd = false; while (!isEnd) { if ((fPos + size) >= fileLength) { size = Convert.ToInt32(fileLength - fPos); isEnd = true; } readData = new byte[size]; fs.Position = fPos;//注意設置讀取的位置 fs.Read(readData, 0, size); Response.BinaryWrite(readData); Response.OutputStream.Flush(); fPos += size; } fs.Close(); Response.OutputStream.Close(); Response.End();//很是重要,沒有這句系統會把頁面的HTML代碼一塊兒輸出的。 Response.Close(); }
相關文章
相關標籤/搜索