简体   繁体   English

如何使用Spring以编程方式使用Rest API中的文件?

[英]How to programmatically consume a file from a Rest API using Spring?

I have the following Rest resource which downloads a file from DB. 我有以下Rest资源从DB下载文件。 It works fine from the browser, however, when I try to do it from a Java client as below, I get 406 (Not accepted error). 它可以在浏览器中正常工作,但是,当我尝试从Java客户端执行此操作时,我得到406(不接受错误)。

...
 @RequestMapping(value="/download/{name}", method=RequestMethod.GET, 
        produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public @ResponseBody HttpEntity<byte[]> downloadActivityJar(@PathVariable String name) throws IOException
{
    logger.info("downloading : " + name + " ... ");
    byte[] file = IOUtils.toByteArray(artifactRepository.downloadJar(name));
    HttpHeaders header = new HttpHeaders();
    header.set("Content-Disposition", "attachment; filename="+ name + ".jar");
    header.setContentLength(file.length);

    return new HttpEntity<byte[]>(file, header);
}
...

The client is deployed on the same server with different port (message gives the correct name) : 客户端部署在具有不同端口的同一服务器上(消息提供正确的名称):

    ...
    RestTemplate restTemplate = new RestTemplate();
    String url = "http://localhost:8080/activities/download/" + message.getActivity().getName();
    File jar = restTemplate.getForObject(url, File.class);
    logger.info("File size: " + jar.length() + " Name: " + jar.getName());
    ...

What am I missing here? 我在这里错过了什么?

The response code is 406 Not Accepted. 响应代码为406 Not Accepted。 You need to specify an 'Accept' request header which must match the 'produces' field of your RequestMapping. 您需要指定一个'Accept'请求标头,该标头必须与RequestMapping的'produce'字段匹配。

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new ByteArrayHttpMessageConverter());    
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM));
HttpEntity<String> entity = new HttpEntity<String>(headers);

ResponseEntity<byte[]> response = restTemplate.exchange(URI, HttpMethod.GET, entity, byte[].class, "1");

if(response.getStatusCode().equals(HttpStatus.OK))
        {       
                FileOutputStream output = new FileOutputStream(new File("filename.jar"));
                IOUtils.write(response.getBody(), output);

        }

A small warning: don't do this for large files. 一个小警告:不要对大文件执行此操作。 RestTemplate.exchange(...) always loads the entire response into memory, so you could get OutOfMemory exceptions. RestTemplate.exchange(...)总是将整个响应加载到内存中,因此您可以获得OutOfMemory异常。 To avoid this, do not use Spring RestTemplate, but rather use the Java standard HttpUrlConnection directly or apache http-components. 为避免这种情况,请不要使用Spring RestTemplate,而是直接使用Java标准HttpUrlConnection或apache http-components。

maybe try this, change your rest method as such: 也许试试这个,改变你的休息方法:

public javax.ws.rs.core.Response downloadActivityJar(@PathVariable String name) throws IOException {
    byte[] file = IOUtils.toByteArray(artifactRepository.downloadJar(name));
    return Response.status(200).entity(file).header("Content-Disposition", "attachment; filename=\"" + name + ".jar\"").build();
}

Also, use something like this to download the file, you are doing it wrong. 此外,使用这样的东西下载文件,你做错了。

org.apache.commons.io.FileUtils.copyURLToFile(new URL("http://localhost:8080/activities/download/" + message.getActivity().getName()), new File("locationOfFile.jar"));

You need to tell it where to save the file, the REST API won't do that for you I don't think. 你需要告诉它保存文件的位置,REST API不会为你做那个我不认为的。

You may use InputStreamResource with ByteArrayInputStream. 您可以将InputStreamResource与ByteArrayInputStream一起使用。

@RestController
public class SomeController {
    public ResponseEntity<InputStreamResource> someResource() {
         byte[] byteArr = ...;
         return ResponseEntity.status(HttpStatus.OK).body(new InputStreamResource(new ByteArrayInputStream(byteArr)));
    }
}

Use this for downloading an JPEG image using exchange. 使用此选项可以使用交换下载JPEG图像。 This works perfect. 这很完美。

URI uri = new URI(packing_url.trim());

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.IMAGE_JPEG));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);

// Send the request as GET
ResponseEntity<byte[]> result= template.exchange(uri, HttpMethod.GET, entity, byte[].class);

out.write(result.getBody());

尝试使用RestTemplate上的execute方法和ResponseExtractor,并使用提取器从流中读取数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 spring 引导应用程序在同一应用程序中使用 rest api 来自同一应用程序中的另一个模块的一个模块 - how can I consume rest api of one module from other module in same application using spring boot application without module dependency 在 Spring Boot Rest api 中使用 excel 文件使用 Json - Consume Json with excel file in spring boot rest api How to Consume Spring-Boot REST API using Retrofit 2 in Android app - How to Consume Spring-Boot REST API using Retrofit 2 in Android app 我们如何在spring中使用Http基本身份验证来使用rest api? - How do we consume rest api with Http basic authentication in spring? 如何在 Spring Boot 应用程序中消费或调用另一个 Rest API? - How to consume or call another Rest API in Spring Boot application? 如何将外部 REST API 响应主体从 json/string 转换/使用到 bean - 我正在使用 Spring Boot-Maven - How do I convert/consume an external REST API response body from json/string to bean - I'm using Spring Boot-Maven 无法使用jQuery使用Spring REST API - Cannot consume Spring REST API with jQuery 如何通过HTTPS使用REST API? - How to Consume a REST API with HTTPS? 如何使用gwt消费远程REST API? - How can you consume a distant rest api using gwt? 使用Spring RestTemplate消耗REST服务 - Consume REST Service using Spring RestTemplate
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM