Spring 3.2に基づいてRESTfulサービスを開発しています。混合マルチパートHTTPリクエストを処理するコントローラーの問題に直面しています。XMLまたはJSON形式のデータを含む2番目の部分と、画像ファイルを含む2番目の部分です。
リクエストの受信に @ RequestPartアノテーション を使用しています
@RequestMapping(value = "/User/Image", method = RequestMethod.POST, consumes = {"multipart/mixed"},produces="applcation/json")
public
ResponseEntity<List<Map<String, String>>> createUser(
@RequestPart("file") MultipartFile file, @RequestPart(required=false) User user) {
System.out.println("file" + file);
System.out.println("user " + user);
System.out.println("received file with original filename: "
+ file.getOriginalFilename());
// List<MultipartFile> files = uploadForm.getFiles();
List<Map<String, String>> response = new ArrayList<Map<String, String>>();
Map<String, String> responseMap = new HashMap<String, String>();
List<String> fileNames = new ArrayList<String>();
if (null != file) {
// for (MultipartFile multipartFile : files) {
String fileName = file.getOriginalFilename();
fileNames.add(fileName);
try {
file.transferTo(new File("C:/" + file.getOriginalFilename()));
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
responseMap.put("displayText", file.getOriginalFilename());
responseMap.put("fileSize", "" + file.getSize());
response.add(responseMap);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Accept", "application/json");
return new ResponseEntity<List<Map<String, String>>>(response,
httpHeaders, HttpStatus.OK);
}
User.Javaは次のようになります-
@XmlRootElement(name = "User")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private int userId;
private String name;
private String email;
private String company;
private String gender;
//getter setter of the data members
}
私の理解では、@ RequestPartアノテーションを使用すると、XMLマルチパートセクションがそのContent-Typeに応じて評価され、最後にユーザークラスに非整列化されることが期待されます(私はJaxb2を使用しており、marshaller/unmarhallerは本文としてXMLデータを渡して@RequestBodyアノテーションを使用すると、アプリケーションコンテキストとプロシージャが他のすべてのコントローラーメソッドで正常に機能します。
しかし実際に起こっていることは、ファイルが正しく検出され、MultipartFileとして解析されても、「ユーザー」の部分は表示されず、リクエストは常に失敗し、コントローラーのメソッドシグネチャと一致しないということです。
複数のクライアントタイプで問題を再現しましたが、マルチパートリクエストのフォーマットは問題ないと確信しています。
この問題を解決するために私を助けてください、多分混合/マルチパートのリクエストを受け取るための回避策があるかもしれません。
よろしくお願いいたします。
ラグベンドラ
私はなんとか問題を解決しました
エンドポイントの例:
@PostMapping("/")
public Document create(@RequestPart Document document,
@RequestPart(required = false) MultipartFile file) {
log.debug("#create: document({}), file({})", delegation, file);
//custom logic
return document;
}
例外:
"error_message": "Content type 'application/octet-stream' not supported"
次のメソッドから例外がスローされます:
org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(HttpInputMessage,MethodParameter,Type)
ソリューション:
HttpMessageConverterまたはHttpMessageConverterを実装し、MediaTypeを認識するカスタムコンバーター@Componentを作成する必要があります。 APPLICATION_OCTET_STREAM。単純な回避策については、を拡張するだけで十分です。AbstractJackson2HttpMessageConverter
@Component
public class MultipartJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
/**
* Converter for support http request with header Content-Type: multipart/form-data
*/
public MultipartJackson2HttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper, MediaType.APPLICATION_OCTET_STREAM);
}
@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return false;
}
@Override
public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) {
return false;
}
@Override
protected boolean canWrite(MediaType mediaType) {
return false;
}
}
問題を修正したかどうかはわかりませんが、@ RequestPartとMultipartFileを混在させると、JSONオブジェクトがコントローラーに取得されないという同様の問題も発生しました。
呼び出しのメソッドシグネチャは正しいように見えます。
public ResponseEntity<List<Map<String, String>>> createUser(
@RequestPart("file") MultipartFile file, @RequestPart(required=false) User user) {
// ... CODE ...
}
ただし、リクエストが次のようになっていることを確認してください。
POST /createUser
Content-Type: multipart/mixed; boundary=B0EC8D07-EBF1-4EA7-966C-E492A9F2C36E
--B0EC8D07-EBF1-4EA7-966C-E492A9F2C36E
Content-Disposition: form-data; name="user";
Content-Type: application/xml; charset=UTF-8
<user><!-- your user xml --></user>
--B0EC8D07-EBF1-4EA7-966C-E492A9F2C36E
Content-Disposition: form-data; name="file"; filename="A551A700-46D4-470A-86E7-52AD2B445847.dat"
Content-Type: application/octet-stream
/// FILE DATA
--B0EC8D07-EBF1-4EA7-966C-E492A9F2C36E--
私は問題を解決することができました:
@SuppressWarnings("rawtypes")
@RequestMapping(value = "/DataTransfer", method = RequestMethod.POST, produces = {
MediaType.APPLICATION_JSON_UTF8_VALUE }, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE} )
@ApiOperation(value = "Sbm Data Transfer Service", response = Iterable.class)
@ApiResponses(value = { @ApiResponse(code = 200, message = "Successfully find."),
@ApiResponse(code = 400, message = "There has been an error."),
@ApiResponse(code = 401, message = "You are not authorized to save the resource"),
@ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"),
@ApiResponse(code = 404, message = "The resource you were trying to reach is not found") })
ResponseEntity processDataTransfer(@RequestPart(name="file") MultipartFile file, @RequestPart(name="param") DataTransferInputDto param);
Org.springframework.web.bind.annotation.RequestPartの@RequestPartを使用できます。 @RequestBodyとファイルアップロードの組み合わせとして使用されます。
このような@RequestParam( "file")MultipartFileファイルを使用すると、ファイルと複数の単一データ(キー値)のみをアップロードできます
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE })
public void saveFile(
@RequestParam("userid") String userid,
@RequestParam("file") MultipartFile file) {
}
あなたは@RequestPartを使用してJSONオブジェクトデータとファイルの両方を投稿することができます
@RequestMapping(value = "/patientp", method = RequestMethod.POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<?> insertPatientInfo(
@RequestPart PatientInfoDTO patientInfoDTO,
@RequestPart("file") MultipartFile file) {
}
マルチパートファイルのアップロードをコントローラーメソッドのパラメーターとして直接使用することに限定されません。フォームオブジェクトにはPartフィールドまたはMultipartFileフィールドを含めることができ、Springはファイルパーツから値を取得し、値を適切に変換する必要があることを自動的に認識します。
上記のメソッドは、単一のファイルを含む以前に示されたマルチパート要求に応答できます。これは、Springにファイルパーツを認識するHTTPメッセージコンバーターが組み込まれているため機能します。 javax.servlet.http.Partタイプに加えて、ファイルのアップロードをorg.springframework.web.multipart.MultipartFileに変換することもできます。 2番目のマルチパートリクエストで示されているように、ファイルフィールドで複数のファイルのアップロードが許可されている場合は、配列またはパーツのコレクションまたはマルチパートファイルを使用するだけです。
@RequestMapping(value = "/patientp", method = RequestMethod.POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<?> insertPatientInfo(
@RequestPart PatientInfoDTO patientInfoDTO,
@RequestPart("files") List<MultipartFile> files) {
}
お力になれて、嬉しいです...