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(); }
相关文章
相关标签/搜索