jackson Spring Cloud开佯攻:字节数组资源的解码器

ippsafx7  于 2022-11-09  发布在  Spring
关注(0)|答案(2)|浏览(110)

我在接口中定义了一个Spring Boot Rest端点,用于下载映像

@GetMapping(value = "/{name}")
ResponseEntity<ByteArrayResource> getFileByName(@PathVariable("name") String name);

我使用Feign Builder来调用这个端点。

Feign.builder()
    .client(new ApacheHttpClient())
    .contract(new SpringMvcContract())
    .decoder(new JacksonDecoder())
    .encoder(new JacksonEncoder())  
    .target(clazz, url)

在调用时,我得到以下错误

com.fasterxml.jackson.core.JsonParseException: Unexpected character ('�' (code 65533 / 0xfffd)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
 at [Source: (BufferedReader); line: 1, column: 2]

当我尝试直接从Insomnia调用端点时,它工作正常。但是通过Feign Builder调用失败。响应内容类型是image/jpeg
在faign中是否有任何特定的解码器来处理ByteArrayResource?我尝试了ResponseEntityDecoderStreamDecoderJacksonDecoder。它们都不起作用。
在调试时,我发现Jackson ObjectMapper readValue失败。我尝试将返回类型从ByteArraySource更改为byte[],也没有成功。
有什么帮助吗?

wpx232ag

wpx232ag1#

我写了自己的小解码器,问题解决了。下面是解码器

private Decoder byteArrayResourceDecoder() {
        Decoder decoder = (response, type) -> {
            if (type instanceof Class && ByteArrayResource.class.isAssignableFrom((Class) type)) {
                return StreamUtils.copyToByteArray(response.body().asInputStream());
            }
            return new JacksonDecoder().decode(response, type);
        };

        return new ResponseEntityDecoder(decoder);
    }

希望这个模板能帮助其他有类似问题的人。希望Feign有支持所有返回类型的解码器。

1rhkuytd

1rhkuytd2#

谢谢Maz-您的解决方案帮了我的忙。
我修改了您的解决方案,以满足我阅读Spring StreamingResponseBody的需要
1.)创建解码器 Package ,该 Package 返回JacksonDecoder(默认)或将responsebody读入字节数组。

Decoder decoder = (response, type) -> {

                Map<String, Collection<String>> headers = response.headers();
                Collection<String> contentType = null;
                for (String x : headers.keySet()){
                    if ("content-type".equals(x.toLowerCase())){
                        contentType = headers.get(x);                      
                    } 
                }

                if (contentType == null || contentType.stream().filter(x -> x.contains("application/json")).findFirst().isPresent()) {                    
                    return new JacksonDecoder(getMapper()).decode(response, type);
                }

                InputStream initialStream = response.body().asInputStream();
                byte[] buffer = new byte[512];
                byte[] result = null;

                try(ByteArrayOutputStream out = new ByteArrayOutputStream()) {
                    try {
                        int length = 0;
                        while ((length = initialStream.read(buffer)) != -1) {
                            out.write(buffer, 0, length);
                        }
                    } finally {
                        out.flush();
                    }
                    result = out.toByteArray();
                } finally {
                    initialStream.close();
                }

                return result;
            };

2.)将自定义解码器与Feign.Builder一起使用

Feign.Builder builder = Feign.builder()
                    // --
                    .decoder(decoder)
                    // --

openfeignfeignspringstreamingresponsebody

相关问题