Moraes
Moraes

Reputation: 495

Receiving a PDF response from server with retrofit

I've a view that generates an PDF document. It's works fine at the browsers (desktop), but my final objective is to deliver it over an android application.

Right now i'm using the retrofit library to handle my requests/responses (only json).

My problem is the data type I need to pass on the Callback<> to handle/receive the PDF data and then save it to the disk?

Upvotes: 1

Views: 4120

Answers (1)

Moraes
Moraes

Reputation: 495

For everyone wondering a human way to do that here is my workflow:

1 - After Generating the PDF file grab the bytes and convert it to base64 string.

I can easily do that with python using pyfpdf lib and using Django as back-end:

import base64

def my_view(request):
    pdf = MyCustomPDF()
    pdf.add_page()
    pdf.set_margins(12,3,3)
    pdf.render() # PDF is ready to be saved
    b = pdf.output('output.pdf','B') # got the PDF as a byte array
    return JsonResponse(
        {  
            "name" : "my_doc.pdf",
            "content64" : base64.b64encode(b).decode('utf8')
        }
    )

remember this example can be done with other backends/libs!

2 - On you Android project set a string field on the model you want to use to receive the PDF response/callback. So our PDF will arrive like this.

{  
    "name" : "my_doc.pdf",
    "content64" : "aGVsbG8gd29ybGQ="
}

So on Java we can set a custom POJO

class PDF{
    private String name;
    private String content64;

    // (...)
}

3 - The base64 will be a simple string! To get the real file as bytes just write a routine like this

class PDF{
    private String name;
    private String content64;

    // (...)

    public byte[] content64AsByteArray(){ // Helps you convert string to byte formats :B
        return Base64.decode(content64,Base64.DEFAULT);
    }

    public String save(String path) {

        try {

            String path = Environment.getExternalStorageDirectory() + "/" + path;

            File f1 = new File(path);

            OutputStream out = null;
            out = new FileOutputStream(path + "/" + this.name);
            out.write(this.content64AsByteArray());
            out.close();


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return this.path; // I like to return it because i can use it to start a "open file" intent
    }
}

4 - the receive callback would be like this with the retrofit

pdfCallback = new Callback<PDF>() {

    @Override public void success(PDF pdf, Response response) {

        if (response.getStatus() == 200) {

            String pathToPDF = pdf.save() // save PDF

        }

    }

    @Override public void failure(RetrofitError error) {
        (...)
    }
}

MyAPI.callbacks.getPDF( (...), pdfCallback);

Upvotes: 3

Related Questions