Sending pdf data through rest api inside json

39,029

Solution 1

We are doing the same, basically sending PDF as JSON to Android/iOS and Web-Client (so Java and Swift).

The JSON Object:

public class Attachment implements Serializable {
    private String name;
    private String content;
    private Type contentType; // enum: PDF, RTF, CSV, ...

    // Getters and Setters
}

And then from byte[] content it is set the following way:

public Attachment createAttachment(byte[] content, String name, Type contentType) {
    Attachment attachment = new Attachment();
    attachment.setContentType(contentType);
    attachment.setName(name);
    attachment.setContent(new String(Base64.getMimeEncoder().encode(content), StandardCharsets.UTF_8));
}

Client Side Java we create our own file type object first before mapping to java.io.File:

public OurFile getAsFile(String content, String name, Type contentType) {
    OurFile file = new OurFile();
    file.setContentType(contentType);
    file.setName(name);
    file.setContent(Base64.getMimeDecoder().decode(content.getBytes(StandardCharsets.UTF_8)));
    return file;
  }

And finally:

public class OurFile {
    //...
    public File getFile() {
        if (content == null) {
          return null;
        }
        try {
          File tempDir = Files.createTempDir();
          File tmpFile = new File(tempDir, name + contentType.getFileEnding());
          tempDir.deleteOnExit();
          FileUtils.copyInputStreamToFile(new ByteArrayInputStream(content), tmpFile);
          return tmpFile;
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
     }

Solution 2

Yes so the problem was with the client.

while decoding we should use

byte[] decodedBytes = Base64.decodeBase64(fileJson.getString("fileContent"));

rather than

byte[] decodedBytes = Base64.decodeBase64(fileJson.get("fileContent").toString());

Since encoded data.toString() yields some think else

Also replaced encodeBase64URLSafeString with encodeBase64String Well quite a simple solution :)

Solution 3

In my REST application with PHP:

  1. Send the data encoded in base64 $data = base64_encode($data) to REST.

  2. Before writing the file, I decode $data = base64_decode($data).

  3. Therefore, when the file is downloaded, it is already in the correct format.

Share:
39,029
rasty
Author by

rasty

Updated on May 30, 2020

Comments

  • rasty
    rasty almost 4 years

    I have made a webservice that send multiple pdfs as response to client using mutlipart/formdata but as it happens one of the client is salesforce which does not support mutlipart/ formdata.

    They want a json in response like - { "filename": xyzname, "fileContent": fileContent }

    I tried encoding data in Base64 using apache codec library but pdf on client side seems to get corrupted and I am unable to open it using acrobat.

    Please find code below -

    import org.apache.commons.io.FileUtils;
    //------Server side ----------------
    @POST
    @Consumes(MULTIPART_FORM_DATA)  
    @Produces(MediaType.APPLICATION_JSON)
    @Path("somepath")
    public Response someMethod(someparam)   throws Exception
    {
    ....
    JSONArray filesJson = new JSONArray();
    String base64EncodedData =      Base64.encodeBase64URLSafeString(loadFileAsBytesArray(tempfile));
    JSONObject fileJSON = new JSONObject();
    fileJSON.put("fileName",somename);
    fileJSON.put("fileContent", base64EncodedData);
    filesJson.put(fileJSON);
    .. so on ppopulate jsonArray...
    //sending reponse
    responseBuilder =    Response.ok().entity(filesJson.toString()).type(MediaType.APPLICATION_JSON_TYPE)    ;
    response = responseBuilder.build();   
    }
    
    //------------Client side--------------
    
    Response clientResponse = webTarget.request()
                .post(Entity.entity(entity,MediaType.MULTIPART_FORM_DATA));
    String response = clientResponse.readEntity((String.class));
    JSONArray fileList = new JSONArray(response);
    for(int count= 0 ;count< fileList.length();count++)
    {
    JSONObject fileJson = fileList.getJSONObject(count);        
    byte[] decodedBytes = Base64.decodeBase64(fileJson.get("fileContent").toString());
    outputFile = new File("somelocation/" + fileJson.get("fileName").toString()   + ".pdf");                    
    FileUtils.writeByteArraysToFile(outputFile,        fileJson.get("fileContent").toString().getBytes());
    }
    
    -------------------------------
    

    Kindly advise.

  • rasty
    rasty almost 8 years
    Thanks for resposne. 1. I did try encodeBase64String which didnt worked. 2. I would build some local code in eclipse to test this out rather than client/api
  • rasty
    rasty almost 8 years
    So I did try encoding and decoding locally an it works so problem may be the way rest api is transferring the data.-----------------------------------File inputFile = new File("some pdf"); String base64EncodedData = Base64.encodeBase64String(loadFileAsBytesArray(partiaFile)); //decode data File decodedFile = new File("some other pdf"); byte[] decodedBytes = Base64.decodeBase64(base64EncodedData); writeByteArraysToFile(decodedFile, decodedBytes);
  • The_GM
    The_GM almost 8 years
    Definitely - that or the client. If you can use Postman to call the Webservice, try that and then use the linux coreutils to decode the resulting string out to file, then try opening with a PDF viewer. This will tell you whether it's the rest REST encoding or the way the client is processing it. Sorry I'm not more immediate help, this is an interesting problem.