ログ日記

作業ログと日記とメモ

Wicket 1.5 でファイルダウンロード

Wicket 1.5 になってAbstractResourceStreamWriterがかなり変わってる。
AbstractResourceStreamWriterはwicket-coreにあるんだけど、IResourceStreamやAbstractResourceStreamはwicket-utilにある。
rc2だからまだ作ってる最中なんだろうか。


取り敢えずAbstractResourceStreamWriterを使ってみたら、実装する必要があるメソッドが多くて、writeの引数がOutputStreamではなくResponseになってる。


どういう意図で変更されたのか分かってないが、取り敢えず以前と同じように使うためのクラスを書いた。

import org.apache.wicket.request.Response;
import org.apache.wicket.util.resource.AbstractResourceStream;
import org.apache.wicket.util.resource.IResourceStreamWriter;
import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
import org.apache.wicket.util.time.Time;

@SuppressWarnings("serial")
public abstract class SimpleResourceStreamWriter extends AbstractResourceStream implements IResourceStreamWriter{
    @Override
    public InputStream getInputStream()
            throws ResourceStreamNotFoundException {
        throw new IllegalStateException("getInputStream is not used with IResourceStreamWriter");
    }

    @Override
    public Time lastModifiedTime()
    {
        return Time.now();
    }
    @Override
    public void close() throws IOException {
    }

    /**
     * @see org.apache.wicket.request.resource.AbstractResource#writeStream
     */
    @Override
    public void write(final Response response) {
        OutputStream out = new OutputStream(){
            @Override
            public void write(int b) throws IOException
            {
                response.write(new byte[] { (byte)b });
            }

            @Override
            public void write(byte[] b) throws IOException
            {
                response.write(b);
            }

            @Override
            public void write(byte[] b, int off, int len) throws IOException
            {
                if (off == 0 && len == b.length)
                {
                    write(b);
                }
                else
                {
                    byte copy[] = new byte[len];
                    System.arraycopy(b, off, copy, 0, len);
                    write(copy);
                }
            }
        };

        write(out);
    }

    protected abstract void write(OutputStream out);
}
        // 使い方
        add(new Link<Void>("test"){
            @Override
            public void onClick() {
                final HSSFWorkbook book = new HSSFWorkbook();
                book.createSheet("test");

                IResourceStream resourceStream = new SimpleResourceStreamWriter(){
                    @Override
                    protected void write(OutputStream out) {
                        try {
                            book.write(out);
                        } catch (IOException e) {
                            throw new WicketRuntimeException(e);
                        }
                    }
                };

                getRequestCycle().scheduleRequestHandlerAfterCurrent(
                    new ResourceStreamRequestHandler(resourceStream)
                    .setFileName("book.xls").setContentDisposition(ContentDisposition.ATTACHMENT));
            }
        });

元々存在するファイルはDownloadLinkで簡単にリンクを作れるので、一時ファイルを作ってからDownloadLinkを使ってもいいかも。