Это обязательно для того, чтобы вы могли POST поток байтов для любого API, который будет принимать файл, или это зависит от API? - PullRequest
0 голосов
/ 26 августа 2018

Я пришел к выводу, что знание этого указывает на недостаток знаний о том, как работают REST-подобные API-интерфейсы, и если кто-то может дать мне ссылку, где я могу узнать историю вопроса, я был бы признателен.В то же время, я также был бы признателен за помощь в ответе на этот вопрос!

У меня есть Java-приложение, которое отправляет файлы из локальной файловой системы в API.Моя цель состоит в том, чтобы вместо того, чтобы миллионы файлов сидели на томе со всеми их файловыми дескрипторами, я хочу оставить файлы в файле .tar.gz, а затем в памяти вытащить их из архива и отправить их без записина диск.Я знаю, что могу записать их на диск, POST их, а затем удалить их, но я рассматриваю этот вариант как последнее средство.

Итак, вот код, который работает для POST файла, который существует в файловой системе,отсутствует в архиве

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

Я получаю ответ JSON от моего конкретного API, который выглядит следующим образом

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

Я поместил этот же файл в архив .tar.gz.и я использовал сжатие Apache Commons для распаковки файла и извлечения каждого файла как TarArchiveEntry, и я проверил, что он работает правильно, записав текстовый файл на диск и открыв его вручную вне Java - я определенно получаю запись впамять правильно.Я попытался изменить сущность, присоединенную к POST, на ByteArrayEntity и преобразовать запись архива в поток байтов, но API настаивает, что он будет принимать только составную сущность.Итак, глядя на API для MultipartEntityBuilder.addBinaryBody, я обнаружил, что у меня осталось две опции: я могу опубликовать байтовый массив или 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 голосов
/ 28 августа 2018

Похоже, что API, который принимает файл, не заботится, прибывает ли он из файлового объекта или байтового массива.Согласно JB Nizet:

В качестве имени файла вы передаете NULL.При передаче файла в качестве аргумента, фактическое имя файла используется, если вы передали значение NULL в качестве имени файла.Очевидно, этого не произойдет, если вы передадите массив bute.Поэтому укажите ненулевое имя файла в качестве последнего аргумента.Это можно узнать только прочитав javadoc и исходный код MultipartEntityBuilder.Это открытый исходный код: используйте это как преимущество.

В этом конкретном случае добавление случайной строки в качестве последнего аргумента метода сборки устраняет проблему, и API принимает массив байтов в виде файла.

...