Search code examples
javadownloadwicketsamba

Wicket - How to download a file through its stream?


I have what I expect would be a pretty common task, but I can't find any straight-forward answers anywhere, so any help here would be greatly appreciated.

Short version: How can I make an IResourceStream from an SmbFile's inputStream?

Long version: In my Wicket app, I have users fill out a questionnaire and then download a file once they've completed it properly. The file is on a Samba server, so I'm using SmbFile, which is working perfectly, so no issue with that. I'm using the AJAXDownload that was written by Sven Meier, Ernesto Barreiro, and Jordi Deu-Pons because I need my button to have Ajax functionality to check that the form was filled out properly, and then start the download. When I was starting out with the file on my computer, I could simply use

final AJAXDownload download = new AJAXDownload()
        {
            @Override
            protected IResourceStream getResourceStream()
            {                   
                IResourceStream resStream = new FileResourceStream(file);

                return resStream;
            }
            @Override
            protected String getFileName() {
                return fileName;
            }
        };
        form.add(download);

But now that I'm using SmbFile through JCIFS, I can't just make a new FileResourceStream. I found that I can use java.io.File.createTempFile to make a tempfile from the smbFile's inputStream, and then use the temp file like this:

protected IResourceStream getResourceStream()
            {                   
                java.io.File tempFile = null;
                try {
                    tempFile = File.createTempFile(smbFile.getName(), smbFile.getContentType());
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                try {
                    Files.writeTo(tempFile, smbFile.getInputStream());
                } catch (IOException e) {
                    e.printStackTrace();
                }
                IResourceStream resStream = new FileResourceStream(tempFile);
                return resStream;
            }

And this works fine for small files, but I will also have some rather large files and since it makes a temp copy of the file before sending it down, it takes a very long time and is just poor design. Any ideas of how I can get my smbFile downloaded in the wicket app?

Edit: Thanks to Joop Eggen, and the book 'Enjoying Web Development with Wicket' by Kent Ka lok Tong, I have the solution below in case anyone else ends up in a similar situation:

final AJAXDownload download = new AJAXDownload()
        {
            @Override
            protected IResourceStream getResourceStream()
            {                   
                IResourceStream resStream = new AbstractResourceStream() {
                    InputStream inStream;
                    public InputStream getInputStream() throws ResourceStreamNotFoundException{
                        try {
                            inStream = smbFile.getInputStream();
                        } catch (IOException e) {                               
                            e.printStackTrace();
                        }
                        return inStream;
                    }
                    public void close() throws IOException {
                        inStream.close();
                    }
                    public String getContentType() {
                        return smbFile.getContentType();
                    }
                };
                return resStream;
            }
            @Override
            protected String getFileName() {
                return smbFileName;
            }
        };
        form.add(download);

Solution

  • You should derive a SmbResourceStream that extends AbstractResourceStream, and implement providing an InputStream for reading by overriding getInputStream and close. You already have smbFile.getInputStream().