rasty
rasty

Reputation: 143

Sending pdf data through rest api inside json

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.

Upvotes: 10

Views: 66778

Answers (4)

rasty
rasty

Reputation: 143

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 :)

Upvotes: 3

seBaka28
seBaka28

Reputation: 960

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);
        }
     }

Upvotes: 3

FXLima
FXLima

Reputation: 31

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.

Upvotes: 2

The_GM
The_GM

Reputation: 97

I would change from using "Safe" to just using "string". So change: encodeBase64URLSafeString(...) to: encodeBase64String(...)

The reason is that the "safe" versions actually change the content to preserve URLs before encrypting - I'm totally uncertain what that would do to a PDF, but suspect it is the source of your problem.

If that doesn't do it for you, I suggest encrypting/decrypting right on the server (or a separate test app) and comparing the results while you try to work it out. That way you can see if what you are doing is working, but don't have to go through the whole "start the server, start the client, connect..." process each time, and it will speed your debugging.

Upvotes: 0

Related Questions