Search code examples
springrestangularfilesaver.js

Angular2 download PDF from REST API


I have a REST API which must return a PDF. I have converted the PDF to a byte array and I return it with my REST endpoint.

The payload looks like this:

{"_body":"%PDF-1.4\n%����\n1 0 obj\n<<\n/Type /Catalog\n/Version /1.4\n/Pages 2 0 R\n>>\nendobj\n2 0 obj\n<<\n/Type /Pages\n/Kids [3 0 R]\n/Count 1\n>>\nendobj\n3 0 obj\n<<\n/Type /Page\n/MediaBox [0.0 0.0 612.0 792.0]\n/Parent 2 0 R\n/Contents 4 0 R\n/Resources 5 0 R\n>>\nendobj\n4 0 obj\n<<\n/Filter /FlateDecode\n/Length 51\n>>\nstream\r\nx�s\n��w3T04R\bI�245P0\u0007�\u0014.\r�Ԝ�|�\u0000\u00177��\nM��,.�\u0010.\u0000�\u001f\n�\r\nendstream\nendobj\n5 0 obj\n<<\n/Font 6 0 R\n>>\nendobj\n6 0 obj\n<<\n/F1 7 0 R\n>>\nendobj\n7 0 obj\n<<\n/Type /Font\n/Subtype /Type1\n/BaseFont /Courier-Bold\n/Encoding /WinAnsiEncoding\n>>\nendobj\nxref\n0 8\n0000000000 65535 f\r\n0000000015 00000 n\r\n0000000078 00000 n\r\n0000000135 00000 n\r\n0000000247 00000 n\r\n0000000371 00000 n\r\n0000000404 00000 n\r\n0000000435 00000 n\r\ntrailer\n<<\n/Root 1 0 R\n/ID [<A0C5C7406F668B945EA55D6F36833E8A> <A0C5C7406F668B945EA55D6F36833E8A>]\n/Size 8\n>>\nstartxref\n535\n%%EOF\n","status":200,"ok":true,"statusText":"OK","headers":{"Content-Type":["application/json;charset=UTF-8"]},"type":2,"url":"http://localhost:8090/api/forms/1/submissions/1/pdf"}

I have imported FileSaver in my Angular2 app but I can't find a way to make it work. I need the PDF to be shown as a downloaded file on the client side when it is received. How can I do this? And should I change the way my REST endpoint returns the data?


Solution

  • You need to stream the data back to the client for it to be able to download instead of sending as a byte array. Since Spring is based on servelet, you can do this like so

    .
    .
    .
    protected void doGet(HttpServletRequest req, HttpServletResponse res) {
        Path downloadFile = Paths.get("path/to/your/file");
        res.setContentType("application/octet-stream");
        res.setHeader("Content-Disposition", "attachment;filename="+ downloadFile.getFileName().toString());
        OutputStream os = res.getOutputStream();
        InputStream is = Files.newInputStream(downloadFile);
        byte[] buffer = new byte[1024];
        int read = -1;
        while (((read = is.read(buffer)) != -1) {
            os.write(buffer);
        }
        is.close();
        os.close();
    }
    

    You might want to have error handling, I omitted just for brevity