Robin Sun
Robin Sun

Reputation: 1620

Why byte array becomes string while transferring it via rest template in Java

These are two SpringBoot projects. A is for api service providing, and B is consuming A's service via rest template. It is OK while transferring string. While transferring Excel file via byte array, B receives a string, not byte array.

The api method in A.

@GetMapping(value = "/export")
@ResponseBody
public HSResult exportFile(@RequestParam(value = "fileName", defaultValue = "-1") String fileName,
                           @RequestParam(value = "provider", defaultValue = "-1") String channelId,
                           @RequestParam(value = "fileStatus", defaultValue = "-5") int fileStatus,
                           @RequestParam(value = "cdate", defaultValue = "") String cdate,
                           HttpServletRequest request, HttpServletResponse response) {

  // ...... some logic code
  InputStream inputStream=new FileInputStream(fullPath);
  long fileSize=new File(fullPath).length();
  byte[] allBytes = new byte[(int) fileSize];
  inputStream.read(allBytes);
  result = HSResult.build(200, "exportFile success",allBytes);
  return result;
}

The consuming method in B.

public ResponseEntity downLoadFile(int businessType, String fileName, int fileStatus, HttpServletResponse response) {

    //.......

    ResponseEntity<HSResult> responseEntity = restTemplate.getForEntity(url, HSResult.class);
    HSResult apiResult = responseEntity.getBody();
    byte[] fileData = (byte[]) apiResult.getData();

    //.......

}

A reads an excel file from disk into a byte array before transferring.

enter image description here

But while receving the result in B side, it is string like UEsDBC0AAAAIADhMuVAKVjbC//////////8LABQAX3Jl

enter image description here

Why did this happen? And how to transfer byte array through rest template correctly? Thanks.

PS: The class of HSResult

public class HSResult {

  private Integer status;
  private String msg;
  private Object data;

  //gets and setters    
  //......

}

Upvotes: 0

Views: 4260

Answers (2)

Khalil
Khalil

Reputation: 61

I have used the Gson() class to convert object to json! and it has no problem with byte arrays.

I have this problem when I want to move my codes to spring, so I solved it by serializing byte[] filed:

class ByteArraySerializer: JsonSerializer<ByteArray>() {

    override fun serialize(bytes: ByteArray, jsonGenerator: JsonGenerator, serializerProvider: SerializerProvider?) {
        val intArray = intArray(bytes)
        jsonGenerator.writeArray(intArray, 0, intArray.size)
    }

    private fun intArray(input: ByteArray): IntArray {
        val ret = IntArray(input.size)
        for (i in input.indices) ret[i] = input[i].toInt() // & 0xff -> 0-255
        return ret
    }
}

convert byte array to int array

and then use it in my class:

data class VideoInfo(val durationMS: Int = 0): Serializable {

    @JsonSerialize(using = ByteArraySerializer::class)
    var bytes: ByteArray? = null
}

It will return json object as a below:

{
  "bytes": [-1,-40, ..., 0],
  "durationMS": 8870
}

It is kotlin, You can easily convert it to java :)

Upvotes: 0

Robin Sun
Robin Sun

Reputation: 1620

Finally, I find the root cause. Share it with who may encounter the same issue.

  1. In A side, it puts a byte array in the data field of HSResult, this field is in type object.
  2. While receving this in B side, rest template is trying to cast all the data back into HSResult. When it comes to the byte array, the receving field data is in type object. So rest template does not konw what the specific type it is, then convert the byte array into a string, with some decode. I don't know whether it is exactly UTF8 or GB2312 or else.

How to resolve this? Just specify the receving field with specific type, not object.

public class HSResult {

    private Integer status;
    private String msg;
    private byte[] data;

    //gets and setters  

}

Then everythiing is OK.

Thanks for Ken's reminder. Http is a text protocal, it cannot transfer byte array directly, so byte array must be converted into string at first.

Upvotes: 2

Related Questions