Re: Output PDF
Sounds like in 6.0 they went back to sending two extra requests instead of one extra. I'm assuming this from your statement. I haven't verified this with our application. The first request (the one generated by the user to get the PDF) should still have a valid userAgent (MSIE). The subsequent requests should have the "conType" userAgent. Can you verify this? Virtually, Andre Van Klaveren, SCP On Mon, 14 Mar 2005 13:21:25 -0800, Scott Piker <[EMAIL PROTECTED]> wrote: > This intrigued me, since our app also has some generated PDFs. Sure > enough, there's a double-get occurring w/ our IE clients (IE 6.0). > > Problem is that the "USER_AGENT" header for get #1 & #2 are identical. > In fact, the only difference I can see in all headers is that get #1 has > an "ACCEPT-LANGUAGE" header, whereas get #2 does not. Everything else > is the same > > So what gives? Did MS "fix" the wrong end of this bug in IE6? Is it > safe to just look for the existence of the "ACCEPT-LANGUAGE" header? > > Thanks, > - Scott > > > -Original Message- > From: Andre Van Klaveren [mailto:[EMAIL PROTECTED] > Sent: Monday, March 14, 2005 3:39 PM > To: Struts Users Mailing List; [EMAIL PROTECTED] > Subject: Re: Output PDF > > I'm assuming that your browser client is IE. If so, the reason your > Action is being called twice is because of a "feature" in IE 4.x+. If > your application returns data that is to be handled with an ActiveX > control (ie Adobe Acrobat Reader) the browser sends additional requests > to the server. In IE 4.x and 5 it actually sends three requests. For > IE 5.5+ it sends two. > > Assuming that your using IE 5.5+, the first request is the original > request (duh), but then IE sends a second request to get the > content-type. Who knows why they can't figure this out on the first > request ;) This second request has it's userAgent header set to > "contype". You can solve this problem and increase the performance of > your application by writing a Servlet filter that sits in front of > whatever Actions you have setup to serve PDF content. Have this filter > look at the userAgent header of each request. If it's set to "contype" > just send an an empty response back to the client with the content type > set to "application/pdf". Simple as that. > > Now, the reason your getting an exception in the second code snippet you > provided is because after you do your forward the JSP calls > response.getOutputStream(). This is done behind the scenes but you can > see it if you look at your generated Servlet code. This method can only > be called once during the lifestyle of the request, hence your > exception. > > It's generally a bad idea to have a JSP produce binary content anyway. > They were designed for Text or HTML output. > > I wrote a generic/reusable Servlet whose sole purpose in life is to > write binary content back to a client. I called it BinaryOutputServlet. > You put your binary data (byte[]) and the content type of the data in > the request scope and forward to it. It gets the data and content type > out of the request and writes it back to the client. It can be used for > any type of data this way. I would recommend doing something similar > since Actions are really for control. By writing back to the client > from an Action you are violating the MVC model anyway. > > I hope this helps. Oh, and you can read all about the "feature" of IE > here: > http://support.microsoft.com/default.aspx?scid=kb;EN-US;q293792 > > Virtually, > Andre Van Klaveren, SCP > > On Mon, 14 Mar 2005 14:01:48 -0600, Brad Balmer <[EMAIL PROTECTED]> > wrote: > > I'm using Jasper to create PDF's through my Actions and cannot figure > > out a good way to export the resulting byte[] to the user. > > > > Currently the tail end of my Action class looks like this: > > > > byte[] reportBytes = null; > > > > File jasperReport = new File(location); > > > > try { > > > > reportBytes = JasperRunManager.runReportToPdf(jasperReport.getPath(), > > parameters, dataSource); > > > > log.info("Found : " + reportBytes.length); > > > > } catch (JRException e) { > > > > e.printStackTrace(); > > > > } > > > > response.setContentType("application/pdf"); > > > > response.setContentLength(reportBytes.length); > > > > ServletOutputStream ouputStream = response.getOutputStream(); > > > > ouputStream.write(reportBytes, 0, reportBytes.length
RE: Output PDF
This intrigued me, since our app also has some generated PDFs. Sure enough, there's a double-get occurring w/ our IE clients (IE 6.0). Problem is that the "USER_AGENT" header for get #1 & #2 are identical. In fact, the only difference I can see in all headers is that get #1 has an "ACCEPT-LANGUAGE" header, whereas get #2 does not. Everything else is the same So what gives? Did MS "fix" the wrong end of this bug in IE6? Is it safe to just look for the existence of the "ACCEPT-LANGUAGE" header? Thanks, - Scott -Original Message- From: Andre Van Klaveren [mailto:[EMAIL PROTECTED] Sent: Monday, March 14, 2005 3:39 PM To: Struts Users Mailing List; [EMAIL PROTECTED] Subject: Re: Output PDF I'm assuming that your browser client is IE. If so, the reason your Action is being called twice is because of a "feature" in IE 4.x+. If your application returns data that is to be handled with an ActiveX control (ie Adobe Acrobat Reader) the browser sends additional requests to the server. In IE 4.x and 5 it actually sends three requests. For IE 5.5+ it sends two. Assuming that your using IE 5.5+, the first request is the original request (duh), but then IE sends a second request to get the content-type. Who knows why they can't figure this out on the first request ;) This second request has it's userAgent header set to "contype". You can solve this problem and increase the performance of your application by writing a Servlet filter that sits in front of whatever Actions you have setup to serve PDF content. Have this filter look at the userAgent header of each request. If it's set to "contype" just send an an empty response back to the client with the content type set to "application/pdf". Simple as that. Now, the reason your getting an exception in the second code snippet you provided is because after you do your forward the JSP calls response.getOutputStream(). This is done behind the scenes but you can see it if you look at your generated Servlet code. This method can only be called once during the lifestyle of the request, hence your exception. It's generally a bad idea to have a JSP produce binary content anyway. They were designed for Text or HTML output. I wrote a generic/reusable Servlet whose sole purpose in life is to write binary content back to a client. I called it BinaryOutputServlet. You put your binary data (byte[]) and the content type of the data in the request scope and forward to it. It gets the data and content type out of the request and writes it back to the client. It can be used for any type of data this way. I would recommend doing something similar since Actions are really for control. By writing back to the client from an Action you are violating the MVC model anyway. I hope this helps. Oh, and you can read all about the "feature" of IE here: http://support.microsoft.com/default.aspx?scid=kb;EN-US;q293792 Virtually, Andre Van Klaveren, SCP On Mon, 14 Mar 2005 14:01:48 -0600, Brad Balmer <[EMAIL PROTECTED]> wrote: > I'm using Jasper to create PDF's through my Actions and cannot figure > out a good way to export the resulting byte[] to the user. > > Currently the tail end of my Action class looks like this: > > byte[] reportBytes = null; > > File jasperReport = new File(location); > > try { > > reportBytes = JasperRunManager.runReportToPdf(jasperReport.getPath(), > parameters, dataSource); > > log.info("Found : " + reportBytes.length); > > } catch (JRException e) { > > e.printStackTrace(); > > } > > response.setContentType("application/pdf"); > > response.setContentLength(reportBytes.length); > > ServletOutputStream ouputStream = response.getOutputStream(); > > ouputStream.write(reportBytes, 0, reportBytes.length); > > ouputStream.flush(); > > ouputStream.close(); > > return(null); > > This will display the pdf, but the action class itself somehow get > called a second time as the above log statement is displayed twice. > > I also tried to set the byte[] on the request and forward onto another > page which does: > > <% > > byte[] reportBytes = > (byte[])request.getAttribute("REPORT_BYTES"); > > response.setContentType("application/pdf"); > > response.setContentLength(reportBytes.length); > > ServletOutputStream ouputStream = > response.getOutputStream(); > > ouputStream.write(reportBytes, 0, reportBytes.length); > > ouputStream.flush(); > > ouputStream.close(); > > %> > > But this complains about: getOutputStream() has already been called > for this response
Re: Output PDF
Any time! Virtually, Andre Van Klaveren, SCP On Mon, 14 Mar 2005 14:51:37 -0600, Brad Balmer <[EMAIL PROTECTED]> wrote: > Thanks for the great response. This should take care of all my issues. > > -Original Message- > From: Andre Van Klaveren [mailto:[EMAIL PROTECTED] > Sent: Monday, March 14, 2005 2:39 PM > To: Struts Users Mailing List; [EMAIL PROTECTED] > Subject: Re: Output PDF > > I'm assuming that your browser client is IE. If so, the reason your > Action is being called twice is because of a "feature" in IE 4.x+. If > your application returns data that is to be handled with an ActiveX > control (ie Adobe Acrobat Reader) the browser sends additional > requests to the server. In IE 4.x and 5 it actually sends three > requests. For IE 5.5+ it sends two. > > Assuming that your using IE 5.5+, the first request is the original > request (duh), but then IE sends a second request to get the > content-type. Who knows why they can't figure this out on the first > request ;) This second request has it's userAgent header set to > "contype". You can solve this problem and increase the performance of > your application by writing a Servlet filter that sits in front of > whatever Actions you have setup to serve PDF content. Have this > filter look at the userAgent header of each request. If it's set to > "contype" just send an an empty response back to the client with the > content type set to "application/pdf". Simple as that. > > Now, the reason your getting an exception in the second code snippet > you provided is because after you do your forward the JSP calls > response.getOutputStream(). This is done behind the scenes but you > can see it if you look at your generated Servlet code. This method > can only be called once during the lifestyle of the request, hence > your exception. > > It's generally a bad idea to have a JSP produce binary content anyway. > They were designed for Text or HTML output. > > I wrote a generic/reusable Servlet whose sole purpose in life is to > write binary content back to a client. I called it > BinaryOutputServlet. You put your binary data (byte[]) and the > content type of the data in the request scope and forward to it. It > gets the data and content type out of the request and writes it back > to the client. It can be used for any type of data this way. I would > recommend doing something similar since Actions are really for > control. By writing back to the client from an Action you are > violating the MVC model anyway. > > I hope this helps. Oh, and you can read all about the "feature" of IE here: > http://support.microsoft.com/default.aspx?scid=kb;EN-US;q293792 > > Virtually, > Andre Van Klaveren, SCP > > On Mon, 14 Mar 2005 14:01:48 -0600, Brad Balmer <[EMAIL PROTECTED]> wrote: > > I'm using Jasper to create PDF's through my Actions and cannot figure out > a > > good way to export the resulting byte[] to the user. > > > > Currently the tail end of my Action class looks like this: > > > > byte[] reportBytes = null; > > > > File jasperReport = new File(location); > > > > try { > > > > reportBytes = JasperRunManager.runReportToPdf(jasperReport.getPath(), > > parameters, dataSource); > > > > log.info("Found : " + reportBytes.length); > > > > } catch (JRException e) { > > > > e.printStackTrace(); > > > > } > > > > response.setContentType("application/pdf"); > > > > response.setContentLength(reportBytes.length); > > > > ServletOutputStream ouputStream = response.getOutputStream(); > > > > ouputStream.write(reportBytes, 0, reportBytes.length); > > > > ouputStream.flush(); > > > > ouputStream.close(); > > > > return(null); > > > > This will display the pdf, but the action class itself somehow get called > a > > second time as the above log statement is displayed twice. > > > > I also tried to set the byte[] on the request and forward onto another > page > > which does: > > > > <% > > > > byte[] reportBytes = > > (byte[])request.getAttribute("REPORT_BYTES"); > > > > response.setContentType("application/pdf"); > > > > response.setContentLength(reportBytes.length); > > > > ServletOutputStream ouputStream = response.getOutputStream(); > > > > ouputStream.write(reportBytes, 0, reportBytes.length); > > > > ouputStream.flush(); > > > > ouputStream.close(); > > > > %> > > > > But this complains about: getOutputStream() has already been called for > this > > response > > > > Any ideas? > > > > > > -- > Virtually, > Andre Van Klaveren > SCP > > - > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > -- Virtually, Andre Van Klaveren SCP - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Output PDF
Woh! IE *does not* use the URL to determine content type. It's determined by the MIME type sent back with the response from the server. And, by default, the option to have IE save encrypted data to disk is turned on, so there won't be an issue with PDFs and SSL unless Micro$oft has changed this is XPSP2. I'm running XPSP2 at home and have no problem viewing PDFs over an encrypted connection. Micro$oft would be breaking a lot of clients if they chose to change that setting. Virtually, Andre Van Klaveren, SCP On Mon, 14 Mar 2005 13:43:51 -0700, Larry Meadors <[EMAIL PROTECTED]> wrote: > Why are you doing that in a jsp? You can do it in an action, but it > will not work that well (but it will work better tahn in a jsp, i > promise). > > The other issue is that a URL ending in /foo.do?name=value will not be > seen by IE as a pdf. You should probably use a servlet for this > instead, then you can map the URL like the one above as this: > /foo/name/value/file.pdf, that will trick the browser into thinking > that it is just a static file. > > Another problem you will have is that if you are using ssl, IE will > not allow acrobat to read from the cache. Your users will have to hack > the registry to make it work. > > Larry > > > On Mon, 14 Mar 2005 14:01:48 -0600, Brad Balmer <[EMAIL PROTECTED]> wrote: > > I'm using Jasper to create PDF's through my Actions and cannot figure out a > > good way to export the resulting byte[] to the user. > > > > Currently the tail end of my Action class looks like this: > > > > byte[] reportBytes = null; > > > > File jasperReport = new File(location); > > > > try { > > > > reportBytes = JasperRunManager.runReportToPdf(jasperReport.getPath(), > > parameters, dataSource); > > > > log.info("Found : " + reportBytes.length); > > > > } catch (JRException e) { > > > > e.printStackTrace(); > > > > } > > > > response.setContentType("application/pdf"); > > > > response.setContentLength(reportBytes.length); > > > > ServletOutputStream ouputStream = response.getOutputStream(); > > > > ouputStream.write(reportBytes, 0, reportBytes.length); > > > > ouputStream.flush(); > > > > ouputStream.close(); > > > > return(null); > > > > This will display the pdf, but the action class itself somehow get called a > > second time as the above log statement is displayed twice. > > > > I also tried to set the byte[] on the request and forward onto another page > > which does: > > > > <% > > > > byte[] reportBytes = > > (byte[])request.getAttribute("REPORT_BYTES"); > > > > response.setContentType("application/pdf"); > > > > response.setContentLength(reportBytes.length); > > > > ServletOutputStream ouputStream = response.getOutputStream(); > > > > ouputStream.write(reportBytes, 0, reportBytes.length); > > > > ouputStream.flush(); > > > > ouputStream.close(); > > > > %> > > > > But this complains about: getOutputStream() has already been called for this > > response > > > > Any ideas? > > > > > > - > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > -- Virtually, Andre Van Klaveren SCP - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
RE: Output PDF
Thanks for the great response. This should take care of all my issues. -Original Message- From: Andre Van Klaveren [mailto:[EMAIL PROTECTED] Sent: Monday, March 14, 2005 2:39 PM To: Struts Users Mailing List; [EMAIL PROTECTED] Subject: Re: Output PDF I'm assuming that your browser client is IE. If so, the reason your Action is being called twice is because of a "feature" in IE 4.x+. If your application returns data that is to be handled with an ActiveX control (ie Adobe Acrobat Reader) the browser sends additional requests to the server. In IE 4.x and 5 it actually sends three requests. For IE 5.5+ it sends two. Assuming that your using IE 5.5+, the first request is the original request (duh), but then IE sends a second request to get the content-type. Who knows why they can't figure this out on the first request ;) This second request has it's userAgent header set to "contype". You can solve this problem and increase the performance of your application by writing a Servlet filter that sits in front of whatever Actions you have setup to serve PDF content. Have this filter look at the userAgent header of each request. If it's set to "contype" just send an an empty response back to the client with the content type set to "application/pdf". Simple as that. Now, the reason your getting an exception in the second code snippet you provided is because after you do your forward the JSP calls response.getOutputStream(). This is done behind the scenes but you can see it if you look at your generated Servlet code. This method can only be called once during the lifestyle of the request, hence your exception. It's generally a bad idea to have a JSP produce binary content anyway. They were designed for Text or HTML output. I wrote a generic/reusable Servlet whose sole purpose in life is to write binary content back to a client. I called it BinaryOutputServlet. You put your binary data (byte[]) and the content type of the data in the request scope and forward to it. It gets the data and content type out of the request and writes it back to the client. It can be used for any type of data this way. I would recommend doing something similar since Actions are really for control. By writing back to the client from an Action you are violating the MVC model anyway. I hope this helps. Oh, and you can read all about the "feature" of IE here: http://support.microsoft.com/default.aspx?scid=kb;EN-US;q293792 Virtually, Andre Van Klaveren, SCP On Mon, 14 Mar 2005 14:01:48 -0600, Brad Balmer <[EMAIL PROTECTED]> wrote: > I'm using Jasper to create PDF's through my Actions and cannot figure out a > good way to export the resulting byte[] to the user. > > Currently the tail end of my Action class looks like this: > > byte[] reportBytes = null; > > File jasperReport = new File(location); > > try { > > reportBytes = JasperRunManager.runReportToPdf(jasperReport.getPath(), > parameters, dataSource); > > log.info("Found : " + reportBytes.length); > > } catch (JRException e) { > > e.printStackTrace(); > > } > > response.setContentType("application/pdf"); > > response.setContentLength(reportBytes.length); > > ServletOutputStream ouputStream = response.getOutputStream(); > > ouputStream.write(reportBytes, 0, reportBytes.length); > > ouputStream.flush(); > > ouputStream.close(); > > return(null); > > This will display the pdf, but the action class itself somehow get called a > second time as the above log statement is displayed twice. > > I also tried to set the byte[] on the request and forward onto another page > which does: > > <% > > byte[] reportBytes = > (byte[])request.getAttribute("REPORT_BYTES"); > > response.setContentType("application/pdf"); > > response.setContentLength(reportBytes.length); > > ServletOutputStream ouputStream = response.getOutputStream(); > > ouputStream.write(reportBytes, 0, reportBytes.length); > > ouputStream.flush(); > > ouputStream.close(); > > %> > > But this complains about: getOutputStream() has already been called for this > response > > Any ideas? > > -- Virtually, Andre Van Klaveren SCP - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Output PDF
Why are you doing that in a jsp? You can do it in an action, but it will not work that well (but it will work better tahn in a jsp, i promise). The other issue is that a URL ending in /foo.do?name=value will not be seen by IE as a pdf. You should probably use a servlet for this instead, then you can map the URL like the one above as this: /foo/name/value/file.pdf, that will trick the browser into thinking that it is just a static file. Another problem you will have is that if you are using ssl, IE will not allow acrobat to read from the cache. Your users will have to hack the registry to make it work. Larry On Mon, 14 Mar 2005 14:01:48 -0600, Brad Balmer <[EMAIL PROTECTED]> wrote: > I'm using Jasper to create PDF's through my Actions and cannot figure out a > good way to export the resulting byte[] to the user. > > Currently the tail end of my Action class looks like this: > > byte[] reportBytes = null; > > File jasperReport = new File(location); > > try { > > reportBytes = JasperRunManager.runReportToPdf(jasperReport.getPath(), > parameters, dataSource); > > log.info("Found : " + reportBytes.length); > > } catch (JRException e) { > > e.printStackTrace(); > > } > > response.setContentType("application/pdf"); > > response.setContentLength(reportBytes.length); > > ServletOutputStream ouputStream = response.getOutputStream(); > > ouputStream.write(reportBytes, 0, reportBytes.length); > > ouputStream.flush(); > > ouputStream.close(); > > return(null); > > This will display the pdf, but the action class itself somehow get called a > second time as the above log statement is displayed twice. > > I also tried to set the byte[] on the request and forward onto another page > which does: > > <% > > byte[] reportBytes = > (byte[])request.getAttribute("REPORT_BYTES"); > > response.setContentType("application/pdf"); > > response.setContentLength(reportBytes.length); > > ServletOutputStream ouputStream = response.getOutputStream(); > > ouputStream.write(reportBytes, 0, reportBytes.length); > > ouputStream.flush(); > > ouputStream.close(); > > %> > > But this complains about: getOutputStream() has already been called for this > response > > Any ideas? > > - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Output PDF
I'm assuming that your browser client is IE. If so, the reason your Action is being called twice is because of a "feature" in IE 4.x+. If your application returns data that is to be handled with an ActiveX control (ie Adobe Acrobat Reader) the browser sends additional requests to the server. In IE 4.x and 5 it actually sends three requests. For IE 5.5+ it sends two. Assuming that your using IE 5.5+, the first request is the original request (duh), but then IE sends a second request to get the content-type. Who knows why they can't figure this out on the first request ;) This second request has it's userAgent header set to "contype". You can solve this problem and increase the performance of your application by writing a Servlet filter that sits in front of whatever Actions you have setup to serve PDF content. Have this filter look at the userAgent header of each request. If it's set to "contype" just send an an empty response back to the client with the content type set to "application/pdf". Simple as that. Now, the reason your getting an exception in the second code snippet you provided is because after you do your forward the JSP calls response.getOutputStream(). This is done behind the scenes but you can see it if you look at your generated Servlet code. This method can only be called once during the lifestyle of the request, hence your exception. It's generally a bad idea to have a JSP produce binary content anyway. They were designed for Text or HTML output. I wrote a generic/reusable Servlet whose sole purpose in life is to write binary content back to a client. I called it BinaryOutputServlet. You put your binary data (byte[]) and the content type of the data in the request scope and forward to it. It gets the data and content type out of the request and writes it back to the client. It can be used for any type of data this way. I would recommend doing something similar since Actions are really for control. By writing back to the client from an Action you are violating the MVC model anyway. I hope this helps. Oh, and you can read all about the "feature" of IE here: http://support.microsoft.com/default.aspx?scid=kb;EN-US;q293792 Virtually, Andre Van Klaveren, SCP On Mon, 14 Mar 2005 14:01:48 -0600, Brad Balmer <[EMAIL PROTECTED]> wrote: > I'm using Jasper to create PDF's through my Actions and cannot figure out a > good way to export the resulting byte[] to the user. > > Currently the tail end of my Action class looks like this: > > byte[] reportBytes = null; > > File jasperReport = new File(location); > > try { > > reportBytes = JasperRunManager.runReportToPdf(jasperReport.getPath(), > parameters, dataSource); > > log.info("Found : " + reportBytes.length); > > } catch (JRException e) { > > e.printStackTrace(); > > } > > response.setContentType("application/pdf"); > > response.setContentLength(reportBytes.length); > > ServletOutputStream ouputStream = response.getOutputStream(); > > ouputStream.write(reportBytes, 0, reportBytes.length); > > ouputStream.flush(); > > ouputStream.close(); > > return(null); > > This will display the pdf, but the action class itself somehow get called a > second time as the above log statement is displayed twice. > > I also tried to set the byte[] on the request and forward onto another page > which does: > > <% > > byte[] reportBytes = > (byte[])request.getAttribute("REPORT_BYTES"); > > response.setContentType("application/pdf"); > > response.setContentLength(reportBytes.length); > > ServletOutputStream ouputStream = response.getOutputStream(); > > ouputStream.write(reportBytes, 0, reportBytes.length); > > ouputStream.flush(); > > ouputStream.close(); > > %> > > But this complains about: getOutputStream() has already been called for this > response > > Any ideas? > > -- Virtually, Andre Van Klaveren SCP - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]