Reputation: 615
I do have a form where the user can put in an ID. When the form is submitted the application should direct respond with a file download. The tricky spot is: instead of a downloadlink I need a direct file repsonse, so the users don't have to click a downloadlink. The site shouldn't change so the user can immediately put another ID into the form and can fire the next form-submit for download. How do I respond in the onSubmit()-Method of my form and keep the site displayed?
Is there a standard solution or pattern I can use with Wicket? Do you have any examples?
Thanks in advance.
Upvotes: 4
Views: 4585
Reputation: 1767
This will be a long post
Ok, I will post two solutions - with and without ajax. If I understand you correctly, you want to submit form with one parameter and initiate file downloading, remaining on the same page to be able to input different parameter and submit form again.
Request/Response handling (no Ajax).
In my comments I suggest you to use another servlet, but you can avoid this, by handling form onSubmit
method. I will assume that you know how to set outputStream for response and will hide this implementation.
First, you have a page or a panel with a form in java:
public class HomePage extends WebPage {
/*input text of the input field. (your ID).*/
private String input;
....
/*initialization method, called from constructor(or place this in constructor).*/
private void init()
{
/*Form with overrided onSubmit method. Has Void generic, because doesn't map any object as a model.*/
Form<Void> form = new Form<Void>("form")
{
@Override
protected void onSubmit() {
/*This is the case. You can get request and response from RequestCycle, but you have to cast them (response at least) to WebRequest/WebResponse, to access required methods.*/
/*----------------------------------------------------*/
WebRequest req = (WebRequest)RequestCycle.get().getRequest();
WebResponse resp = (WebResponse)RequestCycle.get().getResponse();
/* Get request parameter. Id of the parameter is equals to text field id. Also you can check to null or emptyness of the parameter here. */
String idParameter = req.getPostParameters().getParameterValue("input").toString();
...
/* Creating file or your implementation of the stream */
File file = ...;
/* Use proper content type for each file. */
resp.setContentType("application/pdf");
resp.addHeader("Content-Disposition", "attachment; filename=" + fileName);
resp.setContentLength((int) file.length());
FileInputStream fileInputStream = ...
...
/* Write file to response */
while ((bytes = fileInputStream.read()) != -1) {
responseOutputStream.write(bytes);
}
...
/*That's all.*/
}
};
/* Add TextField to form and set PropertyModel for this field.*/
form.add(new TextField<String>("input", new PropertyModel<String>(this, "input")));
/* Don't forget to add form itself */
add ( form );
}
}
in html:
...
<!-- You can also specify target="_blank" parameter for form-->
<form wicket:id="form">
<input type="text" wicket:id="input" />
</form>
...
You even don't need submit button, and can press Enter after text input. That's all.
Ajax handling.
First of all, you need to implement AJAXDownload class. It is very common class and I wonder why it does not included in a standart wicket libraries. It's implementation you can look here. There is no much code.
Ok, and now, using same page class, just update init method in java:
private void init() {
final AJAXDownload download = new AJAXDownload() {
@Override
protected IResourceStream getResourceStream() {
/*Implementing resource according to input ID*/
return createResourceStream(input);
}
};
add ( download );
/*Now, we don't override form, but use AjaxButton instead*/
Form<Void> form = new Form<Void>("form");
form.add(new TextField<String>("input", new PropertyModel<String>(this, "input")));
/*Every button has onSubmit method. And AjaxButton has it's implementation with AjaxRequestTarget instance, which allows to update any component via ajax.*/
form.add(new AjaxButton("submit", Model.of("Submit"), form) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
/*Initiate download according to AJAXDownload api*/
download.initiate(target);
}
});
add(form);
}
/*Method to implement wicket IResourceStream*/
private IResourceStream createResourceStream(String input) {
return new FileResourceStream(new File(...));
}
Note that you can also override getFileName
method of the AJAXDownload
class.
Update. Forgot to add html changes:
<form wicket:id="form">
<input type="text" wicket:id="input" />
<input type="submit" wicket:id="submit" />
</form>
I have tested every implementation via Wicket 6.17 and it's working. Hope it will help you.
And tell me if this is not what you want to achive.
Upvotes: 4