ModelAttribute is not getting set after forcing a download - spring

Adding an object to a ModelAndView in a Spring controller after forcing a download does not seem to work.
Code at Controller method
ModelAndView view = new ModelAndView("");
view.setViewName("pom-upload");
view.addObject("uploadStatus", "Uploaded pom has been successfully processed!");
response.setHeader("Content-Disposition", "attachment; filename=pom.xml");
IOUtils.copy(inputStreamToDownload, response.getOutputStream());
response.flushBuffer();
return view;
I get the file downloaded successfully.
But when I try to access the "uploadStatus" message in my JSP like
<c:out value="${uploadStatus}"></c:out>
or
div id="status-message" class="alert alert-success" role="alert">${uploadStatus}</div>
I do not get the message from ${uploadStatus}
What could the reason be and how would I fix this?

Ok, it sounds like you want to display a message to the user after they have downloaded a file. A couple options.
User clicks download link. This goes to success page. Success page uses Refresh header or javascript to initiate download. So success comes a little early.
See Detect when browser receives file download for some ideas on detecting when the browser gets the download.

Related

Redirect after downloading the pdf in spring

I'm using spring boot. I wrote code to upload data to database. If something goes wrong, data will be downloaded as a pdf which is wrong. What I want to do is, I have to download that pdf and direct to another page.
#RequestMapping(value = "/doUpload", method = RequestMethod.POST)
public void doUpload(#ModelAttribute("employeeCsvForm") EmpFileUpload fileUpload,HttpServletRequest request, HttpServletResponse response){
// codes for create pdf.
if (errorCount != 0) { //errorCount is the count of error data
File fileEmp = new File("error.pdf");
//downloading the pdf in browser path
if (fileEmp.exists()) {
FileUtils.copyFile(fileEmp, response.getOutputStream());
response.setContentType("application/pdf");
response.setHeader("Content-disposition", "attachment;filename=error.pdf");
response.flushBuffer();
}
}
}
This code downloads the pdf file. But I have to redirect to another page, So I used
response.sendRedirect(request.getContextPath() + "/employee/errorCsv"); after response.flushBuffer(); Its downloading pdf successfully but showing following error.
Error is : getOutputStream() has already been called for this response
When I write the redirect code response.sendRedirect(request.getContextPath() + "/employee/errorCsv"); before response.flushBuffer(); Its directing to other page successfully but not downloading.
I want to do both, I tried my best, but failed. Thanks in advance.
You cannot redirect after you initiate a download.
That's why every page that redirects upon download (think Sourceforge for example) does this by:
first redirecting you to the target page
waiting a couple seconds (possibly optional, but might help load the target page)
then initiating a download using Javascript (for browser, this is in fact another redirect)
Technically, a HTTP redirect is part of HTTP headers. Headers are sent over HTTP before any actual content and cannot be sent once you start sending the body (content) - that's why you got the error.
To the browser, a download is just a special kind of page visit - one that ends up downloading data instead of showing it as a website. Now, you only can initiate a redirect (i.e. direct the browser to visit another page) in a website, you cannot do this if downloading. So the following order of steps cannot possibly work:
Visit initial page
At the initial page, direct browser to download file
Direct browser to visit target page
So what you have to do is swap the steps:
Visit initial website
At the initial page, direct browser to visit target page
At the target page, direct browser to download file

ajax returns page source, not the message

All the answers I saw here or elsewhere on Google were with jquery. This is not jquery.
I send an ajax string to a php file.
The php, among other things, formulates a message string which I echo
back to the client.
The returned string is put up in the client as an alert.
The form is then reset.
The problem is that when I do this it puts up as much of the page source that the alert can handle. If I open developer tools to look at the return, it puts the message up correctly, not the page source. Here is the return snippet in my ajax:
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
alert(ajaxRequest.responseText);
document.getElementById("thisForm").reset();
}
}
The php file does a simple echo of a text string.
What is it about developer tools that makes this run correctly and why doesn't it print out the message in the alert when developer tools is not there?
When I run the backend php by itself, with or without developer tools, it displays the message properly.
Does anyone have any ideas?
More information: I tried to replace the alert and reset with a
display.innerHTML=ajaxRequest.responseText where display is a javascript object formed from getElementById("ajaxReturn") of a "div id="ajaxReturn". It didn't work. When I tried developer tools, it showed the network response text as being the page source.
I also added && this.status == 200 to the if statement. No change.
The problem is solved. I am not deleting this because it might help some other poster who runs into the same problem. I launched the AJAX with an onclick to a javascript function called ajaxFunction(). The html entity containing the onclick had an href="#" in it. Removing that href solved the problem.
I had the exact same issue and my cause was related to having an extra slash in my URL.
Lets say my URL was:
https://example.com/index.php
I had a wrong link as follows:
https://example.com/index.php/
On both instances my server loads the page,
But the Ajax shows the page source as response for:
https://example.com/index.php/
But works fine for:
https://example.com/index.php
The ajax is essentially posting to index.php/ajaxpage.php which then responds with whats on index.php instead of whats on ajaxpage.php

ajax error on current page when redirecting to another page in jsf application

I'm using the following code to redirect to another page,
<p:commandButton value="myRedirectButton" value="#{myBean.val}" rendered="#{myBean.renderThis}"
onclick="remoteRedirect();"/>
<p:remoteCommand name="remoteRedirect" actionListener="#{myBean.redirectToPage}"/>
And the actionListener in java is as follows:
public static void redirectToPage(String url){
FacesContext ctx= FacesContext.getCurrentInstance();
ExternalContext ext=ctx.getExternalContext();
String encodedUrl=ext.encodeRedirectUrl(ctx.getApplication().
getViewHandler.getActionUrl(ctx,url),
new HashMap<String,List<String>>());
ext.redirect(encodedUrl);
}
On clicking the 'myRedirectButton', a js error pops up just before the page redirects saying
"This message is only sent, because project stage is development and no other error listeners are registered".
Does anyone have any ideas on why this is happening?
This message is only sent, because project stage is development and no other error listeners are registered
This will show up when you're using MyFaces, and you have javax.faces.PROJECT_STAGE set to Development in web.xml, and you don't have any jsf.ajax.addOnError listener, and the current request is an Ajax request, and the JS code has thrown an error during that request.
Basically, it's just trying to tell you that you should look in the JS console for the actual error, and/or that you should configure a jsf.ajax.addOnError for more fine grained JS error handling. Once having the detail about the actual JS error, you can easily naildown the cause and solve the problem.
As to the concrete problem, you're basically sending multiple ajax requests at the same time on click of the <p:commandButton>, first one via <p:remoteCommand> and immediately thereafter second one via <p:commandButton>. The first one will perform a redirect and hereby unexpectedly abort the second one before its response can be processed, hereby causing a JS error.
There are basically 2 ways to solve your timing problem:
Move the action from the <p:remoteCommand> to the <p:commandButton> and then remove the onclick and <p:remoteCommand> altogether.
Add a return false; in the end of the onclick to block the <p:commandButton> from sending its own ajax request.

WordPress Ajax Get Request?

I have a page that includes a php file I have written like so
HTML
<div id="playlists_div_holder">
<?php include(dirname(__FILE__) . '/includes/get_playlists.php'); ?>
</div>
I have created a button that will refresh the playlists , incase the user has uploaded (added/removed) anything, and I am trying to do so with an ajax request to get the file and include it back into that div, but I am receiving a 500 error.
I am doing this in WordPress so that may be an issue.
The Button
<span class="button-primary refresh-playlists" onclick="ReloadPlaylists()">Refresh Playlists</span>
Ajax Request
function ReloadPlaylists() {
jQuery.get('<?php echo plugins_url();?>/Player/includes/get_playlists.php', function(data) {
jQuery('#playlists_div_holder').html(data);
alert('Load was performed.');
});
}
Including it works but an ajax get throws a 500 error
It's pretty hard to guess the problem but some simple workarounds that you can use all the time:-
CAUTION! Please take backup of your WordPress before doing anything.
1st workaround:-
Download fresh WordPress copy
Delete every folder, except the wp-content folder.
Upload all the files and folders again, except the wp-content folder.
2nd workaround:-
Rename
wp-content/themes
to
wp-content/themes-backup
Create a new folder:-
wp-content/themes
start copying each theme from themes-backup to themes one by one and see if the error is gone.
Now what you have done with the themes folder, do exactly with the plugins folder.
Based on your comment,
i'm getting call to undefined function get_option on line 8 , which is odd because it works when i include it the first time. Could it be because its calling the same file on the other and it has some sort of variable conflict?
This is because when the plugin in running as an include, all the wp-includes are laoded before your plugin code is execute. However when you make an AJAX call directly to that file, the wp-includes are no loaded hence your get_option() isn't working.
You can fix that by adding include_once("../../../wp-blog-header.php"); on top of your get_playlists.php file. That might break your plugin (not sure) so in that case its safe to use it inside a condition like this
if(stristr($_SERVER["REQUEST_URI"], get_playlists.php))
include_once("../../../wp-blog-header.php");
However once you do that you will get an Error 404 when you make an AJAX request because that URL is not registered in Wordpress URL Rewrite. You can override that by using header() function.
if(stristr($_SERVER["REQUEST_URI"], get_playlists.php)) {
include_once("../../../wp-blog-header.php");
header("HTTP/1.1 200 OK");
}

CakePHP redirect method not redirecting

I am trying to redirect to a new page using CakePHP redirect method but for some reason the redirect is not working. The code I am using to redirect is
public function update_sticky_postition_in_db()
{
$this->autoRender = false;
... // Save info to database
$this->redirect(array('action' => 'tool'));
}
Where tool is the name of the view I am tring to redirect to. To try and speed the process of finding the problem I have checked few things and think I have found the cause of the problem. Basically I am trying to redirect to the view that is currently active which I think is part of the reason why it is not redirecting. I have read that it might have something to do with caching of the page but I am not sure how to solve that issue.
Also when using firebug I can see the redirect is sending a GET request but after that nothing is happening. Do I have to do something with the GET request or should Cake handle that for me. Also I have checked the URL of the GET and it is correct.
It is located within the controller with the correct name as I can view the original tool page.
Also the update_sticky_postition_in_db() method does not have a view (hence why the auto render is set to false), its intended purpose is to update a row in the database from an ajax call.
From your post it seems you're firing the update_sticky_postition_in_db() using ajax call, so that the redirection will not work.
You can do redirection using JavaScript within ajax success method.
In order to do that, you may send some json_encode() message from you above method and checking that status within ajax success method you can do a redirect using window.location.

Resources