如何使用rest模板下载图像?

Posted

技术标签:

【中文标题】如何使用rest模板下载图像?【英文标题】:How to download image using rest template? 【发布时间】:2015-08-18 18:36:20 【问题描述】:

我有以下代码:

restTemplate.getForObject("http://img.championat.com/news/big/l/c/ujejn-runi_1439911080563855663.jpg", File.class);

我特别拍摄了不需要授权且绝对可供所有人使用的图像。

执行以下代码时,我看到以下堆栈跟踪:

org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class java.io.File] and content type [image/jpeg]
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:108)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:559)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:512)
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:243)
    at com.terminal.controller.CreateCompanyController.handleFileUpload(CreateCompanyController.java:615)

我做错了什么?

【问题讨论】:

【参考方案1】:

图像是一个字节数组,所以你需要使用byte[].class对象作为RestTemplate.getForObject的第二个参数:

String url = "http://img.championat.com/news/big/l/c/ujejn-runi_1439911080563855663.jpg";
byte[] imageBytes = restTemplate.getForObject(url, byte[].class);
Files.write(Paths.get("image.jpg"), imageBytes);

要使其正常工作,您需要在应用程序配置中配置 ByteArrayHttpMessageConverter

@Bean
public RestTemplate restTemplate(List<HttpMessageConverter<?>> messageConverters) 
    return new RestTemplate(messageConverters);


@Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() 
    return new ByteArrayHttpMessageConverter();

我已经在 Spring Boot 项目中对此进行了测试,并且图像已按预期保存到文件中。

【讨论】:

这种方法的缺点是必须将整个文件存储在内存中。对于较小的图像可能没问题,但您仍然可能冒着炸毁堆栈的风险。 我从@g*** 的问题中了解到这是目标 - 将响应主体转换为对象并从那里开始。目前尚不清楚他的用例是否可以接受将文件对象放在内存中。顺便说一句,你能否澄清一下吹堆栈,我不确定我是否遵循(AFAIK 对象应始终在堆上创建,只有引用可以是本地的) 抱歉,你说得对,我的意思是堆...但是是的,无论如何...最好尽可能使用流式 API,恕我直言,以避免将此类内容长期保存在内存中.由于他的目标似乎只是将远程文件保存到本地文件,因此我认为不需要中间 byte[]? 我同意,如果您想处理更大的文件或大流量,流式传输到文件是唯一的方法。更多 Spring 示例:***.com/questions/5673260/…【参考方案2】:

如果你只是需要从 URL 中获取图像,Java 自带 javax.imageio.ImageIO 类,其中包含此方法签名:

   public static BufferedImage read(URL var0) throws IOException;

示例使用:

    try 
      BufferedImage image = ImageIO.read(new URL("http://www.foo.com/icon.png"));
      int height = image.getHeight();
      int width = image.getWidth();
     catch (IOException e) 

【讨论】:

【参考方案3】:

RestTemplate 期望一个类(例如,一些内存中的表示)将来自服务器的响应转换为。例如,它可以转换如下响应:

id: 1, name: "someone"

进入类似的类:

class NamedThing 
    private int id;
    private String name;

    // getters/setters go here

通过调用:

NamedThing thing = restTemplate.getForObject("/some/url", NamedThing.class);

但是,您似乎真正想做的是从服务器获取响应并将其直接流式传输到文件中。有多种方法可以将您的 HTTP 请求的响应正文获取为类似 InputStream 的内容,您可以逐步读取它,然后将其写入 OutputStream(例如您的文件)。

This answer 展示了如何使用来自commons-ioIOUtils.copy() 来做一些肮脏的工作。但是您需要获取文件的 InputStream... 一个简单的方法是使用HttpURLConnection。有一个tutorial 提供更多信息。

【讨论】:

我没有找到可以使用哪种技术来下载文件 ResponseEntity responseEntity = restTemplate.getForObject("img.championat.com/news/big/l/c/…", ResponseEntity.class) 也不起作用 我做了... HttpURLConnection + IOUtils

以上是关于如何使用rest模板下载图像?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AWS 开发工具包从 S3 下载对象 - RESTful

如何正确实现使用 Spring MVC\Boot 返回图像列表的 REST 服务?

如何使用 DJango Rest Framework 上传多个图像?

如何在 Laravel REST API 中使用 PUT 方法更新图像?

如何使用 Swift 3 将图像从 Rest Api 加载到视图中加载方法

如何使用 Swift URLSession 通过 REST api 将图像和其他参数作为表单数据发布?