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.

+3


source to share


1 answer


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.

+1


source







All Articles