java上传图片到服务器

最近在项目中遇到一个问题,就是使用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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值