当前位置: 首页 > 知识库问答 >
问题:

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

孟永望
2023-03-14

我有以下Rest资源,可以从DB下载文件。它在浏览器中工作得很好,但是,当我尝试从Java客户机执行以下操作时,我得到406(Notaccepted error)。

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

我错过了什么?

共有3个答案

万德海
2023-03-14

您可以将InputStreamResource与ByteArrayInputStream一起使用。

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

或许试试这个,改变你的Rest方式:

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不会帮你这么做。

阙奇思
2023-03-14

响应代码是406不接受。您需要指定一个“接受”请求标头,该标头必须与请求映射的“产生”字段匹配。

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

        }

一个小警告:不要对大文件执行此操作。exchange(…)总是将整个响应加载到内存中,因此可能会出现OutOfMemory异常。为了避免这种情况,请不要使用Spring RestTemplate,而是直接使用Java标准的HttpUrlConnection或apache http组件。

 类似资料:
  • 问题内容: 我将Wicket与Wicket Auth Project一起用于表示层,因此将其与Spring Security集成在一起。这是Wicket调用的身份验证方法: 我的Spring Security XML配置的内容(里面)是: 2.3.6节。参考文档的会话固定攻击防护说: 会话固定攻击是一种潜在的风险,恶意攻击者有可能通过访问站点来创建会话,然后诱使另一个用户以相同的会话登录(通过向他

  • 问题内容: 我们使用下面的代码从属性文件中注入具有属性的Spring bean。 有没有一种方法可以通过编程方式访问属性?我试图做一些没有依赖注入的代码。所以我只想要一些这样的代码: 问题答案: 怎么样?

  • 使用 lavas init 创建的模板项目中,在以下场景下都会以编程方式使用 Lavas: server.dev.js 开发环境下的 SPA/SSR 模式。 server.prod.js 生产环境下的 SSR 模式。 可见以编程方式使用 Lavas 的主要场景就是 SSR 模式,而在 SPA 模式下仅仅是供开发服务器使用。因此,如果开发者选择了 SSR 模式,阅读下面的内容将十分有帮助: 如何选择

  • 问题内容: 相反:如何使用Spring Security手动注销用户? 在我的应用程序中,我 注册了一个新用户屏幕 ,该 屏幕 发布到一个控制器中,该控制器在db中创建一个新用户(并进行了一些明显的检查)。然后我希望这个新用户自动登录…我有点想要某种东西像这样 : 编辑 好吧,我几乎已经基于如何使用Spring Security3.1以编程方式登录用户的答案实现了 但是,部署后,jsp无法访问my

  • 问题内容: 我正在尝试编写一个可以自动登录Facebook的Java程序。 到目前为止,我已经获得了下面的代码,可以将主页html页面下载到String中,但是不知道如何发送电子邮件和密码来登录Facebook?Java程序还需要处理返回的Cookie才能保持登录状态吗? } 更新: 我已经使用htmlUnit尝试了以下代码,但是出现以下异常: 有人知道为什么吗? 问题答案: 您应该看一下HTML

  • 问题内容: 我有一个带有用于内容的内部DIV的HTML页面。内部DIV有自己的滚动条。我想自动滚动到DIV中的某个位置。 我怎样才能做到这一点?(请注意,我不想自动滚动“窗口”滚动条-我已经知道如何执行此操作) 需要跨平台解决方案 问题答案: div具有您可以设置的属性(及其pal,)。