簡體   English   中英

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

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

我有以下Rest資源從DB下載文件。 它可以在瀏覽器中正常工作,但是,當我嘗試從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);
}
...

客戶端部署在具有不同端口的同一服務器上(消息提供正確的名稱):

    ...
    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());
    ...

我在這里錯過了什么?

響應代碼為406 Not Accepted。 您需要指定一個'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);

        }

一個小警告:不要對大文件執行此操作。 RestTemplate.exchange(...)總是將整個響應加載到內存中,因此您可以獲得OutOfMemory異常。 為避免這種情況,請不要使用Spring RestTemplate,而是直接使用Java標准HttpUrlConnection或apache http-components。

也許試試這個,改變你的休息方法:

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();
}

此外,使用這樣的東西下載文件,你做錯了。

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

你需要告訴它保存文件的位置,REST API不會為你做那個我不認為的。

您可以將InputStreamResource與ByteArrayInputStream一起使用。

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

使用此選項可以使用交換下載JPEG圖像。 這很完美。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM