読者です 読者をやめる 読者になる 読者になる

AjaxButton でダウンロード実行

Wicket

WicketAjaxButton でファイルダウンロードを実装しようと、ファイルダウンロードの方法自体に、いろんな方法があるだろうけど、、

IRequestHandler handler = new ResourceStreamRequestHandler(resource,downloadName);
getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);


など、scheduleRequestHandlerAfterCurrent を使うよくある方法、
でももう一度探したら、Wicket6 のドキュメントで以下のページを発見、
https://cwiki.apache.org/confluence/display/WICKET/AJAX+update+and+file+download+in+one+blow

でも、AjaxButton onSubmit で、RequestCycle replaceAllRequestHandlers を実行する PageClass に、setResponsePage すれば済むことである。

それでも見つけた上のURLページに書いてある AjaxBehavior の方法は興味深いので、
余計なものを削除して書き直してみる。

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.behavior.AbstractAjaxBehavior;
import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
import org.apache.wicket.request.resource.ContentDisposition;
import org.apache.wicket.util.resource.IResourceStream;
/**
 * AJAXDownload.
 */

public abstract class AJAXDownload extends AbstractAjaxBehavior{
   protected abstract IResourceStream getResourceStream();
   /**
    * ダウンロード実行.
    * @param target AjaxRequestTarget
    */

   public void callBackDownload(AjaxRequestTarget target){
       target.appendJavaScript("setTimeout(\"window.location.href='" + getCallbackUrl().toString() + "'\", 100);");
   }
   @Override
   public void onRequest(){
      try{
         ResourceStreamRequestHandler handler = new ResourceStreamRequestHandler(getResourceStream(),
 URLEncoder.encode(getFileName(), "UTF-8"));
         handler.setContentDisposition(ContentDisposition.ATTACHMENT);
         getComponent().getRequestCycle().scheduleRequestHandlerAfterCurrent(handler);
      }catch(UnsupportedEncodingException e){
         throw new RuntimeException(e.getMessage(), e);
      }
   }

   protected String getFileName(){
      return null;
   }

}


これを使う WebPage のサンプル、、、

public class AjaxButtonTypePage extends WebPage{
   String info;
   String downloadname;

   public AjaxButtonTypePage(){
      final TextField<String> infoField = new TextField<String>("info", new Model<String>());
      final TextField<String> downloadnameField = new TextField<String>("downloadname", new Model<String>());

      final AJAXDownload download = new AJAXDownload(){
         @Override
         protected IResourceStream getResourceStream(){

            return new AbstractResourceStreamWriter(){
               @Override
               public void write(OutputStream out){
                  try{
                     // TODO OutputStreamに、ダウンロードコンテンツを出力する。
                     // 可変なダウンロードコンテンツ出力をする為に、
                     // Text入力フィールドの値を、AjaxButton で
                     // getInput() → ページのインスタンス経由(※)で取得して
                     // ダウンロードコンテンツ出力のパターンが変わる。
                     // このサンプルは、ダウンロードファイル名を兼ねる

                  }catch(Exception e){
                     throw new RuntimeException(e);
                  }
               }
               @Override
               public String getContentType() {
                  return "application/pdf";
               }
            };
         }
         @Override
         protected String getFileName() {
            return downloadname +".pdf";
         }
      };
      Form<Void> form = new Form<Void>("form");
      form.add(new AjaxButton("download"){
         @Override
         protected void onSubmit(AjaxRequestTarget target, Form<?> f){
            info = infoField.getInput();
            downloadname = downloadnameField.getInput();
            // コールバックでダウンロード実行
            download.callBackDownload(target);
         }
      }.add(download));

      form.add(infoField);
      form.add(downloadnameField);
      add(form);
   }
}

===============
Form 入力に従い、AjaxButton の機能を使いつつ、他のUIの部品と共存させる画面も可能であろう。