是否一定要使您可以将字节流发布到将接受文件的任何API,还是取决于该API?

时间:2018-08-26 19:44:03

标签: java rest apache-commons-httpclient

我了解到,这表明缺乏对类似REST的API的工作原理的了解,如果有人可以向我提供参考资料,使我可以学习该问题的背景知识,我将不胜感激。不过,与此同时,我也希望能帮助您回答这个问题!

我有一个Java应用程序,可将文件从本地文件系统发布到API。我的目标是要避免将数百万个文件和所有文件句柄一起放在卷上,而是将文件保留在.tar.gz文件中,然后在内存中将其从存档中拉出并过帐而无需编写它们到磁盘。我知道我可以将它们写入磁盘,然后将其发布,然后将其删除,但是我认为该选项是最后的选择。

因此,这里的代码可以发布文件系统中存在的文件,而不是归档文件中的文件

public CloseableHttpResponse submit (File file) throws IOException {
    CloseableHttpClient client = HttpClients.createDefault();
    HttpPost post = new HttpPost(API_LOCATION + API_BASE);
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addBinaryBody("files", file, ContentType.APPLICATION_OCTET_STREAM, null);
    HttpEntity multipartEntity = builder.build();
    post.setEntity(multipartEntity);

    CloseableHttpResponse response = client.execute(post);
    System.out.println("response: " + IOUtils.toString(response.getEntity().getContent(),"UTF-8"));
    client.close();
    return response;
}

我从特定的API返回了JSON响应

response: {"data":[<bunch of json>]}

我已将同一文件放入.tar.gz档案中,并使用apache commons压缩解压缩该文件并将其作为TarArchiveEntry拉出,并且我已经通过编写文本文件测试了它是否可以正常工作到磁盘并在Java外部手动打开它-我绝对可以正确地将条目输入内存。我尝试将附加到POST的实体更改为ByteArrayEntity并将存档条目转换为字节流,但是API坚持认为它将仅接受多部分实体。因此,看一下MultipartEntityBuilder.addBinaryBody的API,看来我有两个选择:我可以发布字节数组或InputStream。我已经尝试了两者,但都无法正常工作-我将为字节数组方法发布示例代码,但是我无法弄清楚如何将tar存档转换为InputStream-至少在没有转换的情况下首先将其保存为字节数组,这在当时似乎有点愚蠢。

public CloseableHttpResponse submit (byte[] xmlBytes) throws IOException {
    CloseableHttpClient client = HttpClients.createDefault();
    HttpPost post = new HttpPost(API_LOCATION + API_BASE);
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    builder.addBinaryBody("files", xmlBytes, ContentType.APPLICATION_OCTET_STREAM, null);
    HttpEntity multipartEntity = builder.build();
    post.setEntity(multipartEntity);

    CloseableHttpResponse response = client.execute(post);
    System.out.println("response: " + IOUtils.toString(response.getEntity().getContent(),"UTF-8"));
    System.out.println(response.getStatusLine().getStatusCode());
    client.close();
    return response;
}

我相信除了输入参数的数据类型外,代码是相同的。这是我的空响应,状态码为207:

response: {"data":[]}

所以这是我真正的问题:任何接受文件的API都可以接受字节流或字节数组形式的文件吗? API能否说明差异,而我发布文件时实际发生了什么?是否必须将API专门配置为以字节流或字节数组的形式接受此文件?引用的链接以及简短的解释将受到高度赞赏-我真的需要学习这些知识并很好地理解它。

我在犯一些容易纠正的错误吗?我使用了错误的Content-Type之类的东西吗?我什至不知道MultipartEntityBuilder.build的第三个参数的含义是什么(我留为空的那个)。

感谢您的帮助,非常感谢!

1 个答案:

答案 0 :(得分:0)

看来,接受文件的API不在乎它是来自文件对象还是字节数组。根据JB Nizet:

  

您正在传递null作为文件名。当传递File作为参数时,如果传递null作为文件名,则使用File的实际名称。如果您传递屁股阵列,那显然不会发生。因此,请指定一个非空文件名作为最后一个参数。这只能通过阅读javadoc和MultipartEntityBuilder的源代码才能找到。它是开源的:将其作为优势。

在这种情况下,添加一个随机字符串作为build方法的最后一个参数即可解决此问题,API会将字节数组作为文件接受。