2014-09-23 21 views
3

我確實有一個表單,用戶可以放入一個ID。提交表單時,應用程序應直接回覆文件下載。棘手的地方是:而不是downloadlink我需要一個直接文件repsonse,所以用戶不必點擊下載鏈接。該網站不應該改變,以便用戶可以立即將另一個ID放入表單中,並可以觸發下一個表單 - 提交下載。如何在onSubmit()中響應 - 我的表單的方法並保持網站顯示?Apache Wicket:迴應生成的文件沒有DownloadLink

有沒有可以與Wicket一起使用的標準解決方案或模式?你有什麼例子嗎?

在此先感謝。

+0

我懷疑這是不是真的可行的,因爲一個HTTP請求只能(正常),後跟一個響應,這應該是表單頁面或下載。然而,你可能會做的事情是用頁面進行響應,但頁面中的Javascript會觸發下載。 – biziclop 2014-09-23 17:37:46

+1

不明白爲什麼不使用ajax?實現AJAXDownload並將AjaxButton設置爲表單的提交按鈕。它不會響應另一個頁面,並允許您根據表單輸入無限更改要下載的文件。或者我錯過了什麼? – 2014-09-23 18:14:44

+0

我真的需要Ajax嗎?如果我使用純Java-Servlets,則只使用servletResponse.getOutputStream()並將該文件直接寫入響應中。原始網站保留。我如何使用Wicket做到這一點? – shylynx 2014-09-24 08:08:26

回答

1

這將是一個很長的帖子

好吧,我將發佈兩種解決方案 - 使用和不使用AJAX。如果我正確理解你,你想提交一個參數的表單並啓動文件下載,保留在同一頁面上以便能夠輸入不同的參數並重新提交表單。

請求/響應處理(無Ajax)。

在我的意見中,我建議你使用另一個servlet,但你可以通過處理表格onSubmit方法來避免這種情況。我會假設你知道如何設置outputStream來響應,並會隱藏這個實現。

首先,你在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); 
    } 
} 

在HTML

... 
    <!-- You can also specify target="_blank" parameter for form--> 
    <form wicket:id="form"> 
     <input type="text" wicket:id="input" /> 
    </form> 
    ... 

你甚至不需要提交按鈕,可以在文本輸入後按Enter鍵。就這樣。

Ajax處理。

首先,您需要實現AJAXDownload類。這是非常普遍的類,我想知道爲什麼它不包含在一個標準的wicket庫中。它的實現你可以看看here。沒有太多的代碼。

好了,現在,使用相同的頁面類,只是在Java更新init方法

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(...)); 
    } 

請注意,您也可以覆蓋AJAXDownloadgetFileName方法。

更新。忘了補充HTML變化:

<form wicket:id="form"> 
    <input type="text" wicket:id="input" /> 
    <input type="submit" wicket:id="submit" /> 
</form> 

我已經通過檢票6.17測試每一個實現,它的工作。希望它能幫助你。

並告訴我,如果這不是你想要的。

+0

你說得對,我想留總是在同一頁上發起了一個又一個文件下載。順便說一下,我已經實現了你的非Ajax方法,但是我在onSubmit()之後得到了這個錯誤消息。 「ERROR - DefaultExceptionMapper - 發生意外錯誤 java.lang.IllegalStateException:getOutputStream()已被調用此響應」 爲什麼?我只調用一次webResponse.getOutputStream()。 – shylynx 2014-09-25 07:01:33

+0

如果調用HttpServletResponse.getWriter()它可能發生過的地方。見http://grepcode.com/file/repo1.maven.org/maven2/javax.servlet/servlet-api/2.5/javax/servlet/ServletResponse.java#ServletResponse.getOutputStream%28%29的javadoc – 2014-09-25 07:38:20