Apache Wicket: responda con el archivo generado sin DownloadLink
request response (1)
Esta será una larga publicación
Bien, publicaré dos soluciones, con y sin ajax. Si lo entiendo correctamente, quiere enviar el formulario con un parámetro e iniciar la descarga del archivo, permaneciendo en la misma página para poder ingresar diferentes parámetros y enviar el formulario nuevamente.
Manejo de solicitud / respuesta (sin Ajax).
En mis comentarios, le sugiero que use otro servlet, pero puede evitarlo manipulando el formulario en el método de onSubmit
. Asumiré que usted sabe cómo establecer outputStream para la respuesta y ocultará esta implementación.
Primero, tienes una página o un panel con un formulario en 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 );
}
}
en html :
...
<!-- You can also specify target="_blank" parameter for form-->
<form wicket:id="form">
<input type="text" wicket:id="input" />
</form>
...
Incluso no es necesario enviar el botón, y puede presionar Entrar después de la entrada de texto. Eso es todo.
Manejo de Ajax.
En primer lugar, debe implementar la clase AJAXDownload. Es una clase muy común y me pregunto por qué no está incluida en las bibliotecas de wicket estándar. Es una implementación que puedes mirar aquí . No hay mucho código
Ok, y ahora, usando la misma clase de página, simplemente actualiza el método init en 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(...));
}
Tenga en cuenta que también puede anular el método AJAXDownload
clase AJAXDownload
.
Actualización . Olvidé agregar cambios html :
<form wicket:id="form">
<input type="text" wicket:id="input" />
<input type="submit" wicket:id="submit" />
</form>
He probado todas las implementaciones a través de Wicket 6.17 y está funcionando. Espero que te ayude.
Y dime si esto no es lo que quieres lograr.
Tengo un formulario donde el usuario puede ingresar una identificación. Cuando se envía el formulario, la aplicación debe responder directamente con una descarga de archivos. El punto complicado es que, en lugar de un enlace de descarga, necesito una respuesta directa de archivos, por lo que los usuarios no tienen que hacer clic en un enlace de descarga. El sitio no debe cambiar, por lo que el usuario puede colocar inmediatamente otra ID en el formulario y puede iniciar el siguiente formulario: enviar para descargar. ¿Cómo respondo en el método onSubmit () de mi formulario y sigo mostrando el sitio?
¿Existe una solución o patrón estándar que pueda usar con Wicket? ¿Tienes algún ejemplo?
Gracias por adelantado.