Search code examples
htmlhyperlinkxpageslotus-domino

XPages: How to create link to download file from filesystem


i have a pdf file in a folder and i want to download it from an xpage.

Normally this is just html like this:

<a href='file://10.1.0.2/folder1/myfile.pdf'>click and download</a>

I tested that it works using this line in a simple html file. In my Xpage I created a computed field (HTML display) and i added the < a > as value. I see the correct link on hover but on click nothing happens. What is the problem?

Thnx


Solution

  • I have recently solved this kind of problem by writing a download "servlet" as a headless XPage. For link add onclick event:

    sessionScope.put("filepath", file);
    context.redirectToPage("/_download.xsp") 
    

    _download page has beforeRenderResponse event facesContext.responseComplete() and in afterRenderResponse call a java code that reads the file and writes to the output stream. Something like this:

    if (sessionScope.containsKey("filepath")){
        FileDownload.sendFile(sessionScope.filepath);
    }
    

    java class:

    public class FileDownload {
    public static void sendFile(String filepath) {
        File file = new File(filepath);
        if (file.exists()) {
            ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
            HttpServletResponse response = (HttpServletResponse) ec.getResponse();
            response.setContentType(MIME(filepath)); // figure out the type from extension or else
    
            OutputStream out;
            try {
                // for the download dialog
                response.setHeader("Content-disposition",
                        "attachment; filename*=utf-8''" + java.net.URLEncoder.encode(file.getName(), "UTF-8").replace("+", "%20"));
                out = response.getOutputStream();
                FileInputStream in = new FileInputStream(file);
                byte[] buffer = new byte[4096];
                int length;
                while ((length = in.read(buffer)) > 0) {
                    out.write(buffer, 0, length);
                }
                in.close();
                out.flush();
            } catch (IOException e) {
    
            }
        }
    }
    }
    

    Unfortunately for very large files (1Gb or so) it becomes slow, also takes memory about twice the size of the file, but I'm not sure what could I optimize here. I've tried to call out.flush() within the loop, but it has no effect.