Multiple upload & json object file in one POST request on Play Framework

I have a Windows Phone 8 client that makes the following mail request:

public async Task<string> DoPostRequestAsync(String URI, JSonWriter jsonObject, ObservableCollection<byte[]> attachments) { var client = new RestClient(DefaultUri); var request = new RestRequest(URI, Method.POST); request.AddParameter("application/json; charset=utf-8", jsonObject.ToString(), ParameterType.RequestBody); // add files to upload foreach (var a in attachments) request.AddFile("picture", a, "file.jpg"); var content = await client.GetResponseAsync(request); return content; } 

From the RestSharp documentation, I read that adding files to the request, it is automatically created as a "multipart / form-data" request.

The controller for the download operation in Play 2.1 is as follows:

 @BodyParser.Of(BodyParser.Json.class) public static Result createMessage() { JsonNode json = request().body().asJson(); ObjectNode result = Json.newObject(); String userId = json.findPath("userId").getTextValue(); String rayz = json.findPath("message").getTextValue(); Http.MultipartFormData body = request().body().asMultipartFormData(); Http.MultipartFormData.FilePart picture = body.getFile("picture"); if (picture != null) { String fileName = picture.getFilename(); String contentType = picture.getContentType(); File file = picture.getFile(); result.put("status", "success"); result.put("message", "Created message!"); return badRequest(result); } else { result.put("status", "error"); result.put("message", "Message cannot be created!"); return badRequest(result); } } 

Note that on application.conf I set the following to increase the size limit (seems to not work):

 # Application settings # ~~~~~ parsers.text.maxLength=102400K 

Now, every time I try to make a POST request, which I noticed in the debugger, the IsMaxSizeEsceeded variable is always true and that the multipart variable is null. When I tried to load one nu file using the following controller, everything seemed to work fine. Size was not a problem, and a multipart variable was set.

 public static Result singleUpload() { ObjectNode result = Json.newObject(); Http.MultipartFormData body = request().body().asMultipartFormData(); Http.MultipartFormData.FilePart picture = body.getFile("picture"); if (picture != null) { String fileName = picture.getFilename(); String contentType = picture.getContentType(); File file = picture.getFile(); result.put("status", "success"); result.put("message", "File uploaded!"); return badRequest(result); } else { result.put("status", "error"); result.put("message", "File cannot be uploaded!"); return badRequest(result); } } 

The problem is that attachments / files must be sent / uploaded together with the JSON object to the server in one POST request and NOT separately.

Has anyone encountered similar problems before? Is it possible to achieve this: send a json object and several files that will be uploaded to the server in the same POST request with Play 2.1?

+4
source share
1 answer

Found a way to do this ... stop it if someone tries to do something like this in the future.

So, first of all, the RestSharp client request should be executed as follows:

 public async Task<string> DoPostRequestWithAttachmentsAsync(String ext, JSonWriter jsonObject, ObservableCollection<byte[]> attachments) { var client = new RestClient(DefaultUri); var request = new RestRequest(ext, Method.POST); request.RequestFormat = DataFormat.Json; request.AddParameter("json", jsonObject.ToString(), ParameterType.GetOrPost); // add files to upload foreach (var a in attachments) request.AddFile("attachment", a, "someFileName"); var content = await client.GetResponseAsync(request); if (content.StatusCode != HttpStatusCode.OK) return <error>; return content.Content; } 

Now let's move on to playback. The controller is as follows:

 public static Result createMessage() { List<Http.MultipartFormData.FilePart> attachments; String json_str; Http.MultipartFormData body = request().body().asMultipartFormData(); // If the body is multipart get the json object asMultipartFormData() if (body!=null) { json_str = request().body().asMultipartFormData().asFormUrlEncoded().get("json")[0]; attachments= body.getFiles(); } // Else, if the body is not multipart get the json object asFormUrlEncoded() else { json_str = request().body().asFormUrlEncoded().get("json")[0]; attachments = Collections.emptyList(); } // Parse the Json Object JsonNode json = Json.parse(json_str); // Iterate through the uploaded files and save them to the server for (Http.MultipartFormData.FilePart o : attachments) FileManager.SaveAttachmentToServer(o.getContentType(), o.getFile()); return ok(); } 

So the errors in the RestSharp side seemed to be ParameterType.RequestBody on the json object; and in the controller, the size doesn't really change anything. But the important part is not to use @ BodyParser.Of (BodyParser.Json.class) as this will convert the entire request body to a json object. This, in conjunction with files sent to the server, triggers the isMaxSizeExceeded flag.

Finally, multiprocessing files in the controller, as shown above, only the difficult part is that attachments are optional, what needs to be processed.

+8
source

Source: https://habr.com/ru/post/1490767/


All Articles