Apache Wicket: reply with generated file without DownloadLink
I have a form where a user can enter an id. When the form is submitted, the application should respond directly to uploading the file. Hard Spot: Instead of a download link, I want a direct response to the file, so users don't have to click on the download link. The site shouldn't change, so the user can immediately put a different id in the form and can launch the next form-submit for upload. How can I respond in the onSubmit () method of my form and show the site?
Is there a standard solution or pattern I can use with Wicket? Do you have examples?
Thanks in advance.
source to share
This will be a long post
Ok, I'll post two solutions - with and without ajax. If I understand you correctly, you want to submit a form with one parameter and start uploading the file, staying on the same page so that you can enter different parameters and submit the form again.
Request / response processing (no Ajax).
In my comments, I suggest you use a different servlet, but you can avoid this by processing the form method onSubmit
. I assume you know how to set the outputStream for the response and hide this implementation.
First you have a page or 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 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 don't even need a submit button and you can press Enter after entering text. It's all.
Ajax handling.
First of all, you need to implement the AJAXDownload class. This is a very common class and I am wondering why it is not included in the wicket standard library. You can see the implementation here . There is no code.
Ok, and now, using the same page class, just update the 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 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 the getFileName
class method AJAXDownload
.
Update. Forgot to add html changes:
<form wicket:id="form">
<input type="text" wicket:id="input" />
<input type="submit" wicket:id="submit" />
</form>
I tested each implementation through Wicket 6.17 and it worked. Hope this helps you.
And tell me if this is not what you want to achieve.
source to share