javapdfjerseyspring-mybatisspring-jersey

Download the file from database without saving it on server


I want to retrieve the pdf (Stored as BLOB) from Database using jersey api I am using mybatis as data base framework . I am able to download the pdf but the problem is i get the input stream as database to which i save it as file and then pass that it in Response but i don't want to save that file in server , i want file directly to be downloaded to user .

Current Process :

DATABASE-------> input stream-----> File -----------> add to response ----->user downloads it

         retrieving        making file  passing file          user downloads

What i want :

DATABASE---------->input stream------------> add to response -------> user downloads it

         retrieving         passing file              user downloads

I want remove File making in server as data is confidential

Resource interface

@GET
@Path("v1/download/{id}")
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response downloadFile(@PathParam("id") int id) throws IOException, SQLException;

Resource Impl

@Override
public Response downloadFile(int id) throws IOException, SQLException {
    // TODO Auto-generated method stub
    File file = fileUploadService.downloadFile(id);

    ResponseBuilder response = Response.ok(file);
    response.header("Content-Disposition", "attachment;filename=aman.pdf");
    return response.build();
}

Service method

@Override
public File downloadFile(int id) throws IOException {
    // TODO Auto-generated method stub
    File fil=new File("src/main/resources/Sample.pdf");
    FileUploadModel fm =mapper.downloadFile(id);
    InputStream inputStream = fm.getDaFile();
    outputStream = new FileOutputStream(fil);
    int read = 0;
    byte[] bytes = new byte[102400000];

    while ((read = inputStream.read(bytes)) != -1) {
        outputStream.write(bytes, 0, read);
    }
    return fil;
}

This code is working but i want to remove making of file on server side i.e i want to remove File fil=new File("src/main/resources/Sample.pdf"), this operation which is in service method .

Thanks in advance.


Solution

  • Instead of using File, use ByteArrayOutputStream and write to it. Then return the result as a byte[] which you can pass to your Response.ok(content).

    Didn't test this, but something like this:

    public byte[] downloadFile(int id) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        FileUploadModel fm =mapper.downloadFile(id);
        InputStream inputStream = fm.getDaFile();
        int read = 0;
        byte[] bytes = new byte[1024];
    
        while ((read = inputStream.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
        return out.toByteArray();
    }
    

    Also, that's a lot of bytes to allocate to an array. You can experiment with what works for you, but something like 1024 would likely be totally sufficient.

    You'll probably also want to add another header to your response for Content-Type.