为什么字节数组在 Java 中通过 rest 模板传输时变成字符串
Why byte array becomes string while transferring it via rest template in Java
这是两个SpringBoot项目。 A 为 api 提供服务,B 通过 rest 模板消费 A 的服务。传输字符串时可以。通过字节数组传输 Excel 文件时,B 收到一个字符串,而不是字节数组。
A中的api方法
@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;
}
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 在传输之前将 excel 文件从磁盘读取到字节数组中。
但是在B端接收到的结果是UEsDBC0AAAAIADhMuVAKVjbC/////////8LABQAX3Jl这样的字符串
为什么会这样?以及如何通过 rest 模板正确传输字节数组?谢谢。
PS: HSResult
的class
public class HSResult {
private Integer status;
private String msg;
private Object data;
//gets and setters
//......
}
终于找到了根本原因。与可能遇到相同问题的人分享。
- A端在
HSResult
的data
字段中放入了一个字节数组,该字段是object类型。
- 在 B 端接收此信息时,其余模板正试图将所有数据转换回
HSResult
。对于字节数组,接收字段 data
是对象类型。所以 rest 模板不知道它是什么具体类型,然后将字节数组转换为字符串,并进行一些解码。不知道是UTF8还是GB2312还是别的。
如何解决?只需指定特定类型的接收字段,而不是对象。
public class HSResult {
private Integer status;
private String msg;
private byte[] data;
//gets and setters
}
那就一切OK了
感谢 Ken 的提醒。 http是文本协议,不能直接传输byte数组,所以必须先把byte数组转成string。
我已经使用 Gson() class 将对象转换为 json!字节数组也没有问题。
当我想将我的代码移动到 spring 时遇到这个问题,所以我通过序列化 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
然后在我的 class:
中使用它
data class VideoInfo(val durationMS: Int = 0): Serializable {
@JsonSerialize(using = ByteArraySerializer::class)
var bytes: ByteArray? = null
}
它将return json对象如下:
{
"bytes": [-1,-40, ..., 0],
"durationMS": 8870
}
它是 kotlin,你可以轻松地将它转换为 java :)
这是两个SpringBoot项目。 A 为 api 提供服务,B 通过 rest 模板消费 A 的服务。传输字符串时可以。通过字节数组传输 Excel 文件时,B 收到一个字符串,而不是字节数组。
A中的api方法
@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;
}
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 在传输之前将 excel 文件从磁盘读取到字节数组中。
但是在B端接收到的结果是UEsDBC0AAAAIADhMuVAKVjbC/////////8LABQAX3Jl这样的字符串
为什么会这样?以及如何通过 rest 模板正确传输字节数组?谢谢。
PS: HSResult
的classpublic class HSResult {
private Integer status;
private String msg;
private Object data;
//gets and setters
//......
}
终于找到了根本原因。与可能遇到相同问题的人分享。
- A端在
HSResult
的data
字段中放入了一个字节数组,该字段是object类型。 - 在 B 端接收此信息时,其余模板正试图将所有数据转换回
HSResult
。对于字节数组,接收字段data
是对象类型。所以 rest 模板不知道它是什么具体类型,然后将字节数组转换为字符串,并进行一些解码。不知道是UTF8还是GB2312还是别的。
如何解决?只需指定特定类型的接收字段,而不是对象。
public class HSResult {
private Integer status;
private String msg;
private byte[] data;
//gets and setters
}
那就一切OK了
感谢 Ken 的提醒。 http是文本协议,不能直接传输byte数组,所以必须先把byte数组转成string。
我已经使用 Gson() class 将对象转换为 json!字节数组也没有问题。
当我想将我的代码移动到 spring 时遇到这个问题,所以我通过序列化 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
然后在我的 class:
中使用它data class VideoInfo(val durationMS: Int = 0): Serializable {
@JsonSerialize(using = ByteArraySerializer::class)
var bytes: ByteArray? = null
}
它将return json对象如下:
{
"bytes": [-1,-40, ..., 0],
"durationMS": 8870
}
它是 kotlin,你可以轻松地将它转换为 java :)