最近在项目中遇到一个问题,就是使用restTemplate调用他们的post接口将图片上传至服务器是,在传入参数时,总是报错:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class
java.io.FileDescriptor and no properties discovered to create BeanSerializer (to avoid exception, disable
SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain:
org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile["inputStream"]->java.io.FileInputStream["fd"])
后来发现是传入的数据格式不正确。(不能直接将MultipartFile类型直接作为参数,因为http通常都是以二进制进行数据传输)
解决方法1:(问题:上传的临时文件在删除时总是失败,貌似图片被什么占用,没有找到什么原因)
将原来MultipartFile类型的文件先上传至系统一个临时文件夹,然后通过
FileSystemResource fileSystemResource = new FileSystemResource(file1);
访问系统资源,将当前获取的fileSystemResource 作为参数上传即可
//将base64转换成MultipartFile类型的文件
MultipartFile file = Base64Util.base64ToMultipart(base64);
String fileName = file.getOriginalFilename();
File file1 = null;
try {
file1 = new File(path+fileName);
} catch (Exception e) {
e.printStackTrace();
}
if(!file1.getParentFile().exists()){
file1.getParentFile().mkdirs();
}
try {
file.transferTo(file1);
} catch (IOException e) {
e.printStackTrace();
}
FileSystemResource fileSystemResource = new FileSystemResource(file1);
HttpHeaders headers = new HttpHeaders();
headers.add("ContentType","multipart/form-data");
MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
map.add("file",fileSystemResource );
HttpEntity<MultiValueMap> httpEntity = new HttpEntity<>(map,headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST,httpEntity,String.class);
解决方法2:
使用ByteArrayResource直接获取文件资源的二进制然后作为参数进行传输:
//将base64转换成MultipartFile类型的文件
MultipartFile file = Base64Util.base64ToMultipart(base64);
String fileName = file.getOriginalFilename();
ByteArrayResource bar = null;
try {
bar = new ByteArrayResource(file.getBytes()){
@Override
public String getFilename() {
return fileName;
}
};
} catch (IOException e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.add("ContentType","multipart/form-data");
MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
map.add("file",bar);
HttpEntity<MultiValueMap> httpEntity = new HttpEntity<>(map,headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST,httpEntity,String.class);
第二种方法的好处就是,不仅省去了上传一次临时文件,也不用在上传完成后对临时文件删除了,但是需要注意的是ByteArrayResource 是不包含文件名称的,因此需要重写它的getFilename返回文件名。因为前端图片是以base64编码传输给我的,因此我需要使用方法转换成MultipartFile文件,下面是base64转换MultipartFile类:
/**
* 自定义的MultipartFile的实现类
*/
public class Base64ToMultipartFileUtil implements MultipartFile {
private final byte[] imgContent;
private final String header;
public Base64ToMultipartFileUtil(byte[] imgContent, String header) {
this.imgContent = imgContent;
this.header = header.split(";")[0];
}
@Override
public String getName() {
return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1];
}
@Override
public String getOriginalFilename() {
return System.currentTimeMillis() + (int) Math.random() * 10000 + "." + header.split("/")[1];
}
@Override
public String getContentType() {
return header.split(":")[1];
}
@Override
public boolean isEmpty() {
return imgContent == null || imgContent.length == 0;
}
@Override
public long getSize() {
return imgContent.length;
}
@Override
public byte[] getBytes() throws IOException {
return imgContent;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(imgContent);
}
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
new FileOutputStream(dest).write(imgContent);
}
}
@Slf4j
public class Base64Util {
/**
* 用于将Base64转换成MultipartFile类型
* @param base64
* @return
*/
public static MultipartFile base64ToMultipart(String base64) {
try {
String[] baseStr = base64.split(",");
BASE64Decoder decoder = new BASE64Decoder();
byte[] b = new byte[0];
b = decoder.decodeBuffer(baseStr[1]);
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {
b[i] += 256;
}
}
return new Base64ToMultipartFileUtil(b, baseStr[0]);
} catch (IOException e) {
log.error(e.getMessage());
return null;
}
}
}
base64转换成MultipartFile方法来自:
https://blog.csdn.net/zhuzhezhuzhe1/article/details/83115888