Как я могу отправить вложенный запрос JSON POST в Java, используя Джерси?
Я использую API конвертер документов под названием cloudconvert. У них нет официальной библиотеки Java, но есть сторонний вариант Java. Мне нужна была небольшая настройка, поэтому я клонировал проект github и добавил его в свой проект. Я отправляю cloudconvert файл.epub и получаю взамен файл.pdf. Если я использую настройки по умолчанию, он работает без проблем и правильно преобразует мой.epub в.pdf. Вот код, который делает это возможным.
Вот что запускает преобразование:
// Create service object
CloudConvertService service = new CloudConvertService("api-key");
// Create conversion process
ConvertProcess process = service.startProcess(convertFrom, convertTo);
// Perform conversion
//convertFromFile is a File object with a .epub extension
process.startConversion(convertFromFile);
// Wait for result
ProcessStatus status;
waitLoop:
while (true) {
status = process.getStatus();
switch (status.step) {
case FINISHED:
break waitLoop;
case ERROR:
throw new RuntimeException(status.message);
}
// Be gentle
Thread.sleep(200);
}
//Download result
service.download(status.output.url, convertToFile);
//lean up
process.delete();
startConversion()
звонки:
public void startConversion(File file) throws ParseException, FileNotFoundException, IOException {
if (!file.exists()) {
throw new FileNotFoundException("File not found: " + file);
}
startConversion(new FileDataBodyPart("file", file));
}
Который вызывает это, чтобы фактически послать запрос POST, используя джерси:
private void startConversion(BodyPart bodyPart) {
if (args == null) {
throw new IllegalStateException("No conversion arguments set.");
}
MultiPart multipart = new FormDataMultiPart()
.field("input", "upload")
.field("outputformat", args.outputformat)
.bodyPart(bodyPart);
//root is a class level WebTarget object
root.request(MediaType.APPLICATION_JSON).post(Entity.entity(multipart, multipart.getMediaType()));
}
До этого момента все работает. Моя проблема заключается в том, что когда происходит преобразование.pdf, который возвращает, имеет очень маленькие поля. cloudconvert предоставляет способ изменить эти поля. Вы можете отправить необязательный параметр JSON converteroptions
и установить поля вручную. Я проверил это с помощью почтальона, и он работает без проблем, я смог получить правильно отформатированный маржинальный документ. Так что знайте, что это возможно. Вот информация POSTMAN, которую я использовал:
@POST : https://host123d1qo.cloudconvert.com/process/WDK9Yq0z1xso6ETgvpVQ
Headers: 'Content-Type' : 'application/json'
Body:
{
"input": "base64",
"file": "0AwAAIhMAAAAA", //base64 file string that is much longer than this
"outputformat": "pdf",
"converteroptions": {
"margin_bottom": 75,
"margin_top": 75,
"margin_right": 50,
"margin_left": 50
}
}
Вот мои попытки правильно отформатировать POST-запрос, я просто не очень разбираюсь в Джерси, и пара ответов, которые я нашел на stack ru, не сработала для меня.
При попытке 1 я попытался добавить строку json как поле Multipart.field. Он не дал мне никаких ошибок и все еще возвратил преобразованный файл.pdf, но поля не изменились, поэтому я не должен отправлять его обратно правильно.
private void startConversion(BodyPart bodyPart) {
String jsonString = "{\"margin_bottom\":75,\"margin_top\":75,\"margin_right\":50,\"margin_left\":50}";
MultiPart multipart = new FormDataMultiPart()
.field("input", "upload")
.field("outputformat", args.outputformat)
.field("converteroptions", jsonString)
.bodyPart(bodyPart);
root.request(MediaType.APPLICATION_JSON).post(Entity.entity(multipart, multipart.getMediaType()));
}
Попытка 2, когда я работал в POSTMAN, он использовал тип input как base64, поэтому я попытался изменить его на этот, но на этот раз он вообще ничего не возвращает, никаких ошибок запроса, просто ошибка тайм-аута на 5-минутной отметке.
//I pass in a File object rather than the bodypart object.
private void startConversion(File file) {
byte[] encoded1 = Base64.getEncoder().encode(FileUtils.readFileToByteArray(file));
String encoded64 = new String(encoded1, StandardCharsets.US_ASCII);
String jsonString = "{\"margin_bottom\":75,\"margin_top\":75,\"margin_right\":50,\"margin_left\":50}";
MultiPart multipart = new FormDataMultiPart()
.field("input", "base64")
.field("outputformat", args.outputformat)
.field("file", encoded64)
.field("converteroptions", jsonString);
root.request(MediaType.APPLICATION_JSON).post(Entity.entity(multipart, multipart.getMediaType()));
}
Попытка 3, после некоторого поиска в Google, как правильно отправлять запросы на json post, я изменил формат. На этот раз он вернул ошибку 400 неверных запросов.
private void startConversionPDF(File file) throws IOException {
byte[] encoded1 = Base64.getEncoder().encode(FileUtils.readFileToByteArray(file));
String encoded64 = new String(encoded1, StandardCharsets.US_ASCII);
String jsonString = "{\"input\":\"base64\",\"file\":\"" + encoded64 + "\",\"outputformat\":\"pdf\",\"converteroptions\":{\"margin_bottom\":75,\"margin_top\":75,\"margin_right\":50,\"margin_left\":50}}";
root.request(MediaType.APPLICATION_JSON).post(Entity.json(jsonString));
}
Попытка 4: Кто-то сказал, что вам не нужно вручную использовать jsonString, вы должны использовать сериализуемые Java-бины. Поэтому я создал соответствующие классы и сделал запрос, как показано ниже. Это же ошибка 400 неверный запрос.
@XmlRootElement
public class PDFConvert implements Serializable {
private String input;
private String file;
private String outputformat;
private ConverterOptions converteroptions;
//with the a default constructor and getters/setters for all
}
@XmlRootElement
public class ConverterOptions implements Serializable {
private int margin_bottom;
private int margin_top;
private int margin_left;
private int margin_right;
//with the a default constructor and getters/setters for all
}
private void startConversionPDF(File file) throws IOException {
byte[] encoded1 = Base64.getEncoder().encode(FileUtils.readFileToByteArray(file));
String encoded64 = new String(encoded1, StandardCharsets.US_ASCII);
PDFConvert data = new PDFConvert();
data.setInput("base64");
data.setFile(encoded64);
data.setOutputformat("pdf");
ConverterOptions converteroptions = new ConverterOptions();
converteroptions.setMargin_top(75);
converteroptions.setMargin_bottom(75);
converteroptions.setMargin_left(50);
converteroptions.setMargin_right(50);
data.setConverteroptions(converteroptions);
root.request(MediaType.APPLICATION_JSON).post(Entity.json(data));
}
Я знаю, что это довольно стена текста, но я хотел показать все разные вещи, которые я пробовал, чтобы не тратить впустую время. Спасибо за любую помощь или идеи, которые могут вам понадобиться, чтобы сделать эту работу. Я действительно хочу заставить его работать с Джерси, потому что у меня есть несколько других конверсий, которые я делаю отлично, им просто не нужны какие-либо конвертеры. Также я знаю, что это возможно, потому что он работает при ручном запуске процесса через POSTMAN.
Cloudconvert api документация для начала конвертации
Github-репозиторий с рекомендуемой сторонней java-библиотекой, которую я использую / модифицирую
1 ответ
Я наконец-то понял. Часы проб и ошибок. Вот код, который сделал это:
private void startConversionPDF(File file) throws IOException {
if (args == null) {
throw new IllegalStateException("No conversion arguments set.");
}
PDFConvert data = new PDFConvert();
data.setInput("upload");
data.setOutputformat("pdf");
ConverterOptions converteroptions = new ConverterOptions();
converteroptions.setMargin_top(60);
converteroptions.setMargin_bottom(60);
converteroptions.setMargin_left(30);
converteroptions.setMargin_right(30);
data.setConverteroptions(converteroptions);
MultiPart multipart = new FormDataMultiPart()
.bodyPart(new FormDataBodyPart("json", data, MediaType.APPLICATION_JSON_TYPE))
.bodyPart(new FileDataBodyPart("file", file));
root.request(MediaType.APPLICATION_JSON).post(Entity.entity(multipart, multipart.getMediaType()));
}