Streaming a file download in managed bean action invoked by a dynamically created CommandButton has no effect - jsf

So I have a method that is correctly creating a CSV file with a bunch of data when called by doGet(HttpServletRequest request, HttpServletResponse response) which is called when I create a button like this:
link = new HtmlOutputLink();
HtmlGraphicImage img = new HtmlGraphicImage();
img.setStyle("background-color: #FFFFFF;");
img.setTitle("Click to Export these requests to csv file");
img.setValue("../images/Export.PNG");
link.getChildren().add(img);
link.setValue(resp.encodeURL(Constants.TXT_ALL_DIV_TEAM_EXPORT_LINK));
cell = new DataTableCell();
cell.setType(CellType.DATA);
cell.setFormat(new Format(Format.CENTER));
cell.addElement(link);
headerRow.addElement(cell);
When the button is clicked the doGet method then calls the method which creates the CSV file (which, again, is working correctly called from doGet).
However, I have to change this from an image to a CommandButton, the command button is a custom class that extends the javax.faces.component.html.HtmlCommandButton package, so now I have this:
HtmlOutputLink link = new HtmlOutputLink();
CommandButton alertsButton = new CommandButton();
alertsButton.setId(UI_EXPORT_ID);
alertsButton.setValue(UI_EXPORT_TXT);
alertsButton.setOnclick("javascript:showWaitLayer();jsCBDupdateComponent('" + "form" + "', this );");
alertsButton.setBlockSubmit(true);
alertsButton.setImmediate(true);
alertsButton.addActionListener(this);
link.getChildren().add(alertsButton);
cell = new DataTableCell();
cell.setType(CellType.DATA);
cell.setFormat(new Format(Format.CENTER));
cell.addElement(link);
headerRow.addElement(cell);
When this button is clicked it calls processAction() in which I instantiate the HttpServletResponse used to pass in to the working method.
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse();
response.setContentType("application/octet-stream");
HomeController homeController = (HomeController) context.getApplication().createValueBinding("#{HomeController}").getValue(context);
homeController.createExportFile(response);
EDIT: Adding the createExportFile method with lots taken out for readability.
EDIT2: I've changed the createExportFile so that no HttpServletResponse needs to be passed in. This way the method doesn't have any dependencies on passed in parameters. Both of the buttons (the one with the img and the one that is the CommandButton) call this method and run through without errors in the exact same method. Only the img button creates the excel file though.
public void createExportFile()
throws IOException, PersistenceException, SQLException {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse resp = (HttpServletResponse) context.getExternalContext().getResponse();
resp.setContentType("application/octet-stream");
resp.setContentLength(500 * this.getWorkAllDivDeptList().size());
resp.setHeader("Content-Disposition", "attachment; filename=\""
+ "AllDivTeam.csv" + "\""); Map<String, HashSet<String>> stateDateMap = new HashMap<String, HashSet<String>>();
ArrayList<DynamicFieldInfo> txtFieldAllList = new ArrayList<DynamicFieldInfo>();
RequestReader kanbanReader;
try {
//Get all of the data from the DB
} catch (MidTierException mte) {
mte.printStackTrace();
}
String rowTxt = getExportRowHdrTxt(txtFieldAllList, addlColCnt);
response.getOutputStream().write(rowTxt.getBytes(), 0, rowTxt.length());
kanbanReader = new RequestReader("");
for (AllActiveWorkListInfo bwi : (ArrayList<AllActiveWorkListInfo>) this
.getFilteredAllDivDeptList()) {
HashSet<String> set = (HashSet<String>) stateDateMap.get(bwi.getMID());
if (null != set && !set.isEmpty()) {
Iterator<String> itr = set.iterator();
while (itr.hasNext()) {
rowTxt = getExportRowTxt(bwi, txtFieldAllList,
kanbanReader, (String) itr.next());
response.getOutputStream().write(rowTxt.getBytes(), 0,
rowTxt.length());
}
} else {
rowTxt = getExportRowTxt(bwi, txtFieldAllList, kanbanReader, "");
response.getOutputStream().write(rowTxt.getBytes(), 0,
rowTxt.length());
}
if (count++ == 200) {
response.getOutputStream().flush();
}
}
response.getOutputStream().flush();
response.getOutputStream().close();
}
Adding Headers:
(Request-Line) POST /kanban/faces/kanbanRepAllDivDeptTickets HTTP/1.1
Accept */*
Accept-Encoding gzip, deflate
Accept-Language en-us
Cache-Control no-cache
Connection Keep-Alive
Content-Length 530
Content-Type application/x-www-form-urlencoded
Cookie _cbdModemCheck=false; JSESSIONID=08ADA3D60982F9D13478AF729D6E5205; s_fid=24245A567AE4BB33-0F8E3B5CF3FBEED7
Host localhost:8080
Referer http://localhost:8080/kanban/faces/kanbanRepAllDivDeptTickets
User-Agent Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3)
When I debug it goes through all of the process to create the csv exactly like when called from doGet but it never opens the dialog to download or cancel. It's throwing no exceptions and I'm completely out of ideas.
Does anyone see where I'm making an incorrect assumption?
Thanks for your time,
Mike

You are no where writing the file to the output stream. You should write your file to the output stream for that.
This is the sample code worked for me. Hope it helps you.
int BUFSIZE = 4096;
int length = 0;
ServletOutputStream outStream = response.getOutputStream();
String mimeType = "text/csv";
response.setContentType(mimeType);
response.setContentLength((int)document.length());
String documentName = document.getName();
response.setHeader("Content-Disposition", "attachment; filename=\"" + yourCsvFileName + "\"");
byte[] byteBuffer = new byte[BUFSIZE];
DataInputStream in = new DataInputStream(new FileInputStream(document));
while((null != in) && ((length = in.read(byteBuffer)) != -1)) {
outStream.write(byteBuffer, 0, length);
}
in.close();
outStream.close();

Related

Gecko WebBrowser unable to open a specific link first time after Restart machine

I am new in C# . I have developed own webbrowser with Gecko webBrowser control. But I'm unable to open a particular link for first time, and it return alert for timeout. I handled timeout alert messagebox too.
When I have implemented
private void gWebBrowser_DocumentCompleted(object sender, Gecko.Events.GeckoDocumentCompletedEventArgs e)
I found out that first time page was not properly loaded.
How can i use auto Reload or timer in it?
My code is:
public partial class Embedded_Browser : Form
{
public Embedded_Browser()
{
string GeminiURL = "NA";
InitializeComponent();
Xpcom.Initialize("Firefox");
GeckoPreferences.User["dom.max_script_run_time"] = 0; //let js run as long as it needs to; prevents timeout errors
GeckoPreferences.User["security.warn_viewing_mixed"] = false;
GeckoPreferences.User["browser.download.manager.showAlertOnComplete"] = false;
GeckoPreferences.User["privacy.popups.showBrowserMessage"] = false;
GeckoPreferences.User["browser.xul.error_pages.enabled"] = false;
GeckoPreferences.User["browser.cache.memory.enable"] = false;
gWebBrowser.NSSError += new EventHandler<GeckoNSSErrorEventArgs>(gWebBrowser_NSSError); //Bypass SSL certificate issues
gWebBrowser.NavigationError += new EventHandler<GeckoNavigationErrorEventArgs>(gWebBrowser_NavigationError); //If there are any issues encountered during page loads
gWebBrowser.Navigated += new EventHandler<GeckoNavigatedEventArgs>(gWebBrowser_Navigated); //React appropriately to URL navigation
string sUserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; pl; rv:1.9.1) Gecko/20090624 Firefox/3.5 (.NET CLR 3.5.30729)";
Gecko.GeckoPreferences.User["general.useragent.override"] = sUserAgent;
var observerService = Xpcom.GetService<nsIObserverService>("#mozilla.org/observer-service;1");
observerService.AddObserver(new Observer(), "http-on-modify-request", false);
if (Environment.Is64BitOperatingSystem)
{
RegistryKey MyReg = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Wow6432Node\\Jekson\\AppConfig", true);
GeminiURL = (string)MyReg.GetValue("Browse_URL", "NA");
}
else
{
RegistryKey MyReg = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Jekson\\AppConfig", true);
GeminiURL = (string)MyReg.GetValue("Browse_URL", "NA");
}
gWebBrowser.Navigate(GeminiURL);
textBox1.Text = GeminiURL;
PromptFactory.PromptServiceCreator = () => new NoPromptService();
// System.Threading.Thread.Sleep(5000);
if(NoPromptService.isPrompt == 1){
gWebBrowser.Reload();
gWebBrowser.Navigate(GeminiURL);
MessageBox.Show("Hello!");
}
}
Please Help me. thanks in advance
I have used timer control for making Web browser auto refresh for first time.
After 5ms web browser auto refresh once.
My code is:
private void timer1_Tick(object sender, EventArgs e)
{
gWebBrowser.Navigate("google.com"); //You can pass any url here which you want to load
if (count == 0)
{
timer1.Enabled = false;
}
count++;
}

Downloading Excel using POST Rest Service

I'm using REST web services provided by Spring Framework.
I need to download an excel sheet but i also need to donwload the sheet on basis of some selected parameters. I'm sending a request class object as the Body to a POST Rest call(#RequestBody)
I could not download the excel using a POST Method. Please help me to achieve this.
#RequestMapping(value = "/search/export", method = RequestMethod.POST,, produces = MediaType.APPLICATION_JSON_VALUE)
public void searchResultToExcel(#RequestBody SearchRequest searchRequest, HttpServletResponse response, HttpServletRequest request) throws Exception
This is my method signature
I've found this thread Return Excel downloadable file from Spring that may be useful.
I also think that content-type you're forcing (produces = MediaType.APPLICATION_JSON_VALUE) might be in the way, at least as far as I could understand the question. I think you should be forcing for an EXCEL content type there (application/vnd.ms-excel).
It says:
You need to set the Content-Disposition header.
response.setHeader("Content-disposition","attachment; filename=" + yourFileName);
and write your bytes directly to the response OutputStream.
File xls = new File("exported.xls"); // or whatever your file is
FileInputStream in = new FileInputStream(xls);
OutputStream out = response.getOutputStream();
byte[] buffer= new byte[8192]; // use bigger if you want
int length = 0;
while ((length = in.read(buffer)) > 0){
out.write(buffer, 0, length);
}
in.close();
out.close();
The above is relatively old. You can construct a ResponseEntity with FileSystemResource now. A ResourceHttpMessageConverter will then copy the bytes, as I have suggested above, for you. Spring MVC makes it simpler for you rather than having you interact with interfaces from the Servlet specification.
#Post
#Path("downloadMyReport")
#Produces("application/excel")
public static Response generatemyExcelReport()throws BusinessException {
try {
File file=null;
Date reportDate=new Date() ;
path="/home/Documents/excelReport/"
file=getReportByName(path);
if(file==null){
logger.info("File is null");
else{
name=capitalizeFirstLater(name);
getReportSummary(reportDate);
FileUtils.writeByteArrayToFile(new File(path),createExcelForReport(fileName,path));
file=getReportByName(path);
}
ResponseBuilder response = Response.ok(file);
response.header("Content-Disposition", "attachment; filename=\"" + fileName2 + "\"");
return response.build();
}
}catch (BusinessException e) {
throw e;
}catch (Exception e) {
logger.error("Exception while generating ExcelSheetForMyReport {}",Utils.getStackTrace(e));
throw new BusinessException("Error in downloading ExcelSheetForMyReport");
}
}
ResponseBuilder response = Response.ok(file);
response.header("Content-Disposition", "attachment; filename=\"" + fileName2 + "\"");
return response.build();

Chrome pdf api doesn't download ServletOutputStream jasper pdf file [duplicate]

This question already has answers here:
How to provide a file download from a JSF backing bean?
(5 answers)
Closed 6 years ago.
I'm trying to show a web printed report made with JasperReports 6.2.0 in an application with JSF 2.2.
Happens that the report is correctly shown, in a new tab, after setting target="_blank" on my h:form, but the download button doesn't work.
Here's the code:
HttpServletResponse response = (HttpServletResponse) FacesContext context = FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.setContentType("application/pdf");
ServletOutputStream responseStream = response.getOutputStream();
ByteArrayInputStream relatorioSourceStream = new ByteArrayInputStream(reportJasper);
JasperPrint jp = JasperFillManager.fillReport(relatorioSourceStream, parameters, getConnection());
File file = new java.io.File(path);
if (file.exists()) {
file.delete();
} else if (file.getParentFile() != null) {
file.getParentFile().mkdirs();
file.createNewFile();
}
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(jp));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(file));
SimplePdfExporterConfiguration conf = new SimplePdfExporterConfiguration();
exporter.setConfiguration(conf);
exporter.exportReport();
InputStream is = new FileInputStream(file);
int read = 0;
byte[] bytes = new byte[4096];
while ((read = is.read(bytes)) != -1) {
responseStream.write(bytes, 0, read);
}
responseStream.flush();
responseStream.close();
Happens that the report is correctly shown, but the download won't do anything.
It's not quite a "save as" option that I want to be shown when the report tab is loaded, It happens that the chrome api's download button tries to save my page (html) instead of saving the content as a .pdf file.
Thanks in advance.
Successfully generated your error: on chomre:Version 51.0.2704.106 m, You have one alternate way on this. You can directly download such file by using
httpServletResponse.addHeader("Content-disposition", "attachment; filename=" + outputFileName);
command also define file name. Hope will find solution to the problem.

How to base.RequestContext.ToOptimizedResultUsingCache() return string for Accept-Encoding: deflate?

I do have following code...
and Accept-Encoding: deflate
public object Get(DTOs.Product request)
{
...
var sCache = base.RequestContext.ToOptimizedResultUsingCache(
this.CacheClient, cacheKey, expireInTimespan, () =>
{
// Business layer returns resultant dataset as XmlDocument
...
return sXML.InnerXml;
});
//returns ServiceStack.Common.Web.HttpResult;
return GenerateResp(sCache, base.Request.Headers["Accept"]);
}
Issue is base.RequestContext.ToOptimizedResultUsingCache returns ServiceStack.Common.Web.CompressedResult even though I am returning XML. I understand that Accept-Encoding: deflate causes RequestContext.CompressionType to deflate.
Above code works fine, when there is no Accept-Encoding (through fiddler test).
But, if the request comes from a browser, it would come as a Compressed, in this case how can I get sCache as string to pass it to GenerateResp?
Thanks for your help.
I am able to resolve the issue by modifying code to...
public object Get(DTOs.Product request)
{
...
var objCache = base.RequestContext.ToOptimizedResultUsingCache(
this.CacheClient, cacheKey, expireInTimespan, () =>
{
// Business layer returns resultant dataset as XmlDocument
...
return sXML.InnerXml;
});
string compressionType = base.RequestContext.CompressionType;
bool doCompression = compressionType != null;
string transformed = "";
if (doCompression)
{
byte[] bCache = ((ServiceStack.Common.Web.CompressedResult)(objCache)).Contents;
transformed = bCache.Decompress(base.RequestContext.CompressionType);
}
else
{
transformed = (string)objCache;
}
//returns ServiceStack.Common.Web.HttpResult;
//In GenerateResp, If compressionType contains "gzip" or "deflate", I compress back the response to respective compression, and add respective Content-Encoding to the header.
return GenerateResp(transformed, base.Request.Headers["Accept"], compressionType);
}
Thank you.

How can I use WebHttpRelayBinding with application/json requests?

When I try to use a generic message handler, I run into errors when the accept, or content-type is html/xml/json if I use my own type such as text/x-json everything works as expected the message is dispatched to my handlers and the stream returns the data to the webclient. I have stepped through this with a debugger and my code successfully creates the message but something in the servicebus binding chokes and causes the server not to respond. Is there a setting I need to change to allow application/json and make the service bus send raw data rather then trying to reserialize it?
[WebGet( UriTemplate = "*" )]
[OperationContract( AsyncPattern = true )]
public IAsyncResult BeginGet( AsyncCallback callback, object state )
{
var context = WebOperationContext.Current;
return DispatchToHttpServer( context.IncomingRequest, null, context.OutgoingResponse, _config.BufferRequestContent, callback, state );
}
public Message EndGet( IAsyncResult ar )
{
var t = ar as Task<Stream>;
var stream = t.Result;
return StreamMessageHelper.CreateMessage( MessageVersion.None, "GETRESPONSE", stream ?? new MemoryStream() );
}
Instead of using: StreamMessageHelper.CreateMessage, you can use the following one after you change :
WebOperationContext.Current.OutgoingResponse.ContentTYpe = "application/json"
public Message CreateJsonMessage(MessageVersion version, string action, Stream jsonStream)
{
var bodyWriter = new JsonStreamBodyWriter(jsonStream);
var message = Message.CreateMessage(version, action, bodyWriter);
message.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));
return message;
}
class JsonStreamBodyWriter : BodyWriter
{
Stream jsonStream;
public JsonStreamBodyWriter(Stream jsonStream)
: base(false)
{
this.jsonStream = jsonStream;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
writer.WriteNode(JsonReaderWriterFactory.CreateJsonReader(this.jsonStream, XmlDictionaryReaderQuotas.Max), false);
writer.Flush();
}
}

Resources