Spring: данные и файл JSON в одном запросе
Я знаю, как создавать конечные точки, которые обрабатывают файлы с помощью MediaType.MULTIPART_FORM_DATA
и @FormDataParam("file") FormDataBodyPart bodyPart
, но мне было интересно, могу ли я также иметь данные JSON по этому запросу? Что-то вроде:
@POST
@Path("somepath")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFileAndJSON(@RequestBody SomeModel someModel,
@FormDataParam("file") FormDataBodyPart bodyPart) {
return null;
}
на данный момент, если я добавлю некоторые данные JSON на вкладке "raw" на следующий запрос почтальона, я получаю HTTP 415 Unsupported Media Type
вероятно, потому, что я указал, что я потребляю MULTIPART_FORM_DATA
но я также использую @RequestBody
который ищет контент JSON, который является APPLICATION_JSON
. Итак, как я могу обрабатывать данные JSON и файл в той же просьбе? Я знаю, что это можно сделать в двух запросах, я просто хочу сделать это в одном, если это возможно?
2 ответов
почему вы используете аннотации Spring и Jersey? Вы должны придерживаться использования аннотаций, предназначенных для фреймворка. Поскольку вы используете Джерси, следует придерживаться его его Примечание.
Итак, вот что нужно учитывать о вашем текущем коде и среде.
- не может быть двух отдельных телах. С вашим кодом, похоже, именно этого вы и ожидаете.
-
вы can хотя поместите JSON как часть многосоставного тела. Для этого вы также должны аннотировать
SomeModel
С@FormDataParam
@POST @Path("somepath") @Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadFileAndJSON( @FormDataParam("model") SomeModel someModel, @FormDataParam("file") FormDataBodyPart bodyPart) { }
в конфигурации Джерси вам нужно обязательно зарегистрировать
MultiPartFeature
. Если вы этого не сделаете, тело не сможет быть десериализовано, и вы получите исключения и ответы на ошибки.-
теперь проблема почтальона. Вы можете увидеть похожие проблемы здесь. Проблема заключалась в том, что
Content-Type
был не установлен для части тела JSON. Например, тело может выглядеть как--AaB03x Content-Disposition: form-data; name="model" {"some":"model", "data":"blah"} --AaB03x Content-Disposition: form-data; name="file"; filename="file1.txt" Content-Type: text/plain ... contents of file1.txt ... --AaB03x--
вы можете увидеть тело, если вы нажмете предварительный просмотр кнопка в почтальоне. Проблема в том, что нет
Content-Type
на"model"
часть, как вы можете видеть в разделе"file"
часть. Это происходит потому, что вы не можете установить отдельные части'Content-Type
в почтальона. Тот, который вы увидите, будет обнаружен из расширения файла. Например,.txt
файл заставит почтальона установитьContent-Type
totext/plain
и доimage/png
.если вы посмотрите в ссылке выше, я предложил, возможно, вы могли бы использовать
.json
файл вместо ввода данных. Конечно, это была только теория. На самом деле я его не проверял.в любом случае
Content-Type
должны быть установлен для того, чтобы Джерси мог знать десериализовать его как JSON. Если.json
теория расширения файлов не работает, тогда вы можете использовать другой клиент, например cURL, который Я показал пример в ссылке, или вы можете использовать клиент Джерси для тестирования, как видно здесь. не устанавливайте до
multipart/form-data
в почтальона. Он устанавливает его для вас, когда вы используете форма-Сведения. Я только что видел сообщение, где кто-то сказал, что есть ошибка, когда вы устанавливаете заголовок. Не могу найти сообщение сейчас, и не то, что я подтвердил, но я бы просто оставил его из.
обновление
Итак, ОП был возможность найти способ установить Content-Type: application/json
"модели" часть. Но иногда бывает так, что с клиентом Javascript вы не можете его установить. Так что не будет Content-Type
. Если это так, Джерси не сможет десериализовать JSON, поскольку он понятия не имеет, что на самом деле отправляется JSON. Если вы абсолютно не можете или не знаете, как установить Content-Type
для индивидуального части, вы можете прибегнуть к следующему.
@POST
@Path("somepath")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFileAndJSON(@FormDataParam("model") FormDataBodyPart jsonPart,
@FormDataParam("file") FormDataBodyPart bodyPart) {
jsonPart.setMediaType(MediaType.APPLICATION_JSON_TYPE);
SomeModel model = jsonPart.getValueAs(SomeModel.class);
}
Да, вы можете получить это как данные составной формы.
вы получаете это в angularjs:
$scope.uploadFile = function () {
var file = $scope.selectedFile[0];
$scope.upload = $upload.upload({
url: 'api/upload',
method: 'POST',
data: angular.toJson($scope.model),
file: file
}).progress(function (evt) {
$scope.uploadProgress = parseInt(100.0 * evt.loaded / evt.total, 10);
}).success(function (data) {
//do something
});
};
$scope.onFileSelect = function ($files) {
$scope.uploadProgress = 0;
$scope.selectedFile = $files;
};
public Response uploadFileAndJSON(@RequestParam("data") String data,
@MultiPartFile("file")File file) {
you can data as form data and convert it
like you want to your object using Gson jar.
return null;
}
посмотреть код в AngularJS : Angularjs как загрузить данные многостраничной формы и файл?
https://puspendu.wordpress.com/2012/08/23/restful-webservice-file-upload-with-jersey/