Spring mvc send an excel as byte array to server error - java

In our spring mvc project we simply send an .xlsx file to the server on a DTO object:
DtoClass {
private String filename;
private byte[] array;
}
now on the server we receive this file through a simple controller.
The problem is when we save this simple excel file on to the disk from this byte[] the file is corrupted.
Any ideas why?
p.s the client sends the byte array with encoding using base64.
Another interesting fact - txt files actually work and can be opened regularly with a text editor after being sent from client-> server

Have a look at MultipartFile.
You can either update the DTO to have MultipartFile as field or can send it directly.
Approach 1 - MultipartFile as part of DTO
Update the DTO as below
DtoClass {
private String filename;
private MultipartFile file;
// getter & setters
}
The controller should look like below
#RequestMapping(value = "/doUpload/", method = RequestMethod.POST )
public void uploadMultipart(
final HttpServletRequest request,
#RequestParam("file") DtoClass dto) { ... }
Approach 2 - MultipartFile sent directly
Here your controller would look like something as below
#RequestMapping(value = "/doUpload/", method = RequestMethod.POST )
public void uploadMultipart(
final HttpServletRequest request,
#RequestParam("file") final MultipartFile multiPartFile) { ... }
P.S.: Make sure you make an entry of <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" /> in your config file.
Also client should set enctype="multipart/form-data"

Related

Spring doesn't return JSON in full

I am using spring boot and #PostMapping trying to return a POJO that contains 1 Multipart file and some String. When i look at Postman i only see half of the Multipart object. File is 3kb. I don't get any errors. When i return the multipart variable null other variables in JSON are being shown in response so they are not empty. How can i return all of the JSON?
public class foo{
public MultipartFile dataFile;
public String project;
public Boolean extract;
... getter - setter - constructor
}
I send it like
#PostMapping
public foo route(#RequestParam("dataFile") MultipartFile dataFile, ... ) {
...
return fooObject;
}
Response
{
"dataFile": {
"name": "dataFile",
"bytes":"MIKCAQYJKoZIhvcNAQcCoIKB8jCCge4CA... (half of the file)
As I thought, the MultipartFile is used to upload object, not to download it. As stated in the Javadoc:
A representation of an uploaded file received in a multipart request.
Which means, it is great for upload, but that is not the case for download.
The easiest way (and the most straightforward) would be to change the MultipartFile to a byte[] and send that to the client.
Here is an example:
public Foo getFile(MultipartFile multipartFile) {
byte[] bytes = multipartFile.getBytes();
return new Foo(bytes, "project");
}

How To Pass Multipart Image File as parameter to a POST REST Service

I have been trying to upload a multipart file in my Java Spring MVC Web Application using a POST REST service method. I have using the following REST service method to upload the file and this works fine when i choose the file using Postman REST service.
#RequestMapping(value="/upload", method=RequestMethod.POST)
public #ResponseBody String handleFileUpload( #RequestParam("file") MultipartFile file, ModelMap model)
{
//codes
}
But when i tried to pass the multipart file as parameter to a POST REST service method in the controller. Its not working fine. So how can i pass multipart file as a queryparam to a POST REST service method.
In my controller class I have:
#RequestMapping(value = "/upload-image", method = RequestMethod.POST)
public String uploadProfileImage(#RequestParam("fileUpload") MultipartFile fileUpload, Model model, HttpServletRequest request, HttpServletResponse response)
{
// codes
}
I have the following bean in my root-context.xml file
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
Any help is appreciated.
It is easy and a little bit strange. Do use #PathVariable instead of #RequestParam. I faced with this situation couple month ago. I do not know why it so, but snippet below works in my project.
#ResponseBody
#RequestMapping(method = RequestMethod.POST, value = "/upload-image", consumes = MULTIPART_FORM_DATA_VALUE, produces = APPLICATION_JSON_VALUE)
public String uploadProfileImage(#PathVariable("fileUpload") MultipartFile file) {
// ...
}
Look at JerseyRestClientMultipartUpload.java to get example how to send MultiPart using Jersey.
final MultiPart multiPart = new FormDataMultiPart()
.field("description", "Picture of Jabba the Hutt", MediaType.TEXT_PLAIN_TYPE)
.field("characterProfile", jsonToSend, MediaType.APPLICATION_JSON_TYPE)
.field("filename", fileToUpload.getName(), MediaType.TEXT_PLAIN_TYPE)
.bodyPart(fileDataBodyPart);
multiPart.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE);
// POST request final
final WebResource resource = client.resource(API_URI)
ClientResponse response = resource.type("multipart/form-data").post(ClientResponse.class, multiPart);

How to send a request upload a file with java object like #RequestParam CommonsMultipartFile file ,#RequestBody User userDetailsId?

I am trying so much to send a request like CommonsMultipartFile and one java object.I constructed controller like follows.
public #ResponseBody Response upload(#RequestParam CommonsMultipartFile userPhoto, #RequestBody UserDetails userDetailsId,
#RequestParam String authCode)
//method impl
}
when I am trying to send request from postman:
In form-data uploaded image(1st screenshot) ,In Body-raw(2nd screenshot) i am sending user object.This is what I done.Can you please tell me how to fix this issue.Or can you please suggest me right way if I am wrong.
Thanks in advance.
#RequestMapping(method = RequestMethod.POST, headers = ("content-type=multipart/*"), produces = "application/json", consumes = "image/*")
public RestResponse save(#RequestParam("bankAddress") String bankAddress, #RequestParam("bankNameAr") String bankNameAr, #RequestParam("bankNameEn") String bankNameEn, #RequestParam("bankPhone") String bankPhone, #RequestParam("bankStatus") BigDecimal bankStatus, #RequestParam("countryId") long countryId,
#RequestParam("bankImage") MultipartFile file) {
.
.
.
}
and use byte[] data = file.getBytes(); to get file into byte[] and use for further process.

Can we use multipart and #RequestBody together in spring?

I want to create a API which can have parameter as multipart file and JSON object (#RequestBody). Please find following snippet while calling this API. I am getting HTTP 415 Unsupported Media Type error. If I remove #RequestBody LabPatientInfo reportData then it works fine.
#RequestMapping(value={"/lab/saveReport"}, method={RequestMethod.POST},
consumes={"multipart/form-data"}, headers={"Accept=application/json"})
#ResponseBody
public ResponseEntity<String>
saveReport(#RequestParam(value="reportFile") MultipartFile reportFile,
#RequestBody LabPatientInfo reportData) throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json; charset=utf-8");
logger.info("in Lab Save Report");
logger.info("Report Data {} ", reportData);
//logger.info("Request BODY {} ", request.getAttribute("data"));
return new ResponseEntity<String>(HttpStatus.OK);
}
following is LabPatientInfo class.
#RooJson(deepSerialize = true)
#RooToString
public class LabPatientInfo {
private String firstName;
private String phoneNumber;
private String DateOfBirth;
private Integer age;
private String gender;
private String refferedBy;
private String reportfile;
private String reportType;
private String reportDate;
private String purpose;
private String followUpDate;
private List<ReportDataInfo> analytes;
while hitting API I am passing following JSON object with uploaded file..
{
"firstName":"abc",
"phoneNumber":"898989",
"DateOfBirth":"asas",
"age":"asas",
"gender":"asas",
"refferedBy":"asas",
"reportfile":"asas",
"reportType":"asas",
"reportDate":"asas",
"purpose":"asas",
"followUpDate":"asas",
"analytes":null
}
You can use #RequestPart like below. This will support both json object and multipart file.
#ResponseBody
public ResponseEntity<String>
saveReport(#RequestPart (value="reportFile") MultipartFile reportFile,
#RequestPart LabPatientInfo reportData) throws IOException {
In order to test it using curl you can create one file for your json part (reportData). Say for example you create "mydata.json" file and paste your json payload in it. And say your reportFile is "report.txt". Now you can send request using curl like below.
curl -v -H "Content-Type:multipart/form-data" -F "reportData=#mydata.json;type=application/json" -F "reportFile=#report.txt;type=text/plain" http://localhost:8080/MyApp/lab/saveReport
An example of a post method which receives a json object and a generic file:
public ResponseEntity<Resource> postGenerateReport(#RequestPart GenerateReportDTO, generateReportDTO, #RequestPart MultipartFile jxhtmlReport)
For the PostMan setup (or curl or anyother REST test utility) you just have to add form-data request with 2 elements:
Key:generateReportDTO, Value: File with .json extension (and compatible content with the object)
Key:jxhtmlReport, Value: just any file.
Gl
When a parameter is annotated with #RequestPart the content of the part is passed through an HttpMessageConverter to resolve the method argument with the 'Content-Type' of the request part in mind. This is analogous to what #RequestBody does to resolve an argument based on the content of a regular request.
so, we can parse #Requestbody as #RequestPart as "abaghel" and reportData need to be a json file.
Spring Roo 2.0.0.M3 includes support for automatic scaffolding of a REST API.
For complete information, see the REST API in the reference manual.
Note the M3 version generate artifacts that could change in newer versions, so your project might not upgrade automatically if you open it with RC1 or above.
May the Force be with you.

Receiving a MultiPart file and JSON data using Spring and AngularJS

Here's my controller below:
#RequestMapping(value="/upload", method=RequestMethod.PUT)
public ResponseEntity<String> handleFileUpload(
#RequestParam("file") MultipartFile file,
#RequestParam("data") String campaignJson,
Principal principal) throws JsonParseException, JsonMappingException, IOException {
I want to be able to receive a MultipartFile as well as a JSON string containing data associated to the file (title, description, etc).
I can get MultipartFile uploading to work on it's own, and I can receive a JSON string and parse it on its own, but when I have them together in 1 controller, it fails. Whenever I print out the String campaignJson it says [object Object] instead of the data that I'm sending (when I print out the data being sent in angular, it's in correct JSON format.)
I've tried #RequestBody, #RequestParam, #RequestPart, but to no avail.
My question is: How do I receive both a MultipartFile and data in the form of JSON in one Spring controller?
This worked for me :
#RequestMapping(value = "/{id}/upload", method = RequestMethod.PUT)
public DocumentResource uploadPut(#PathVariable("id") Long id,
MultipartHttpServletRequest request,
HttpServletResponse response) {
String next = request.getFileNames().next();
MultipartFile file = request.getFile(next);
.....
}
Edit :
Using the MultipartHttpServletRequest should not limit you in any way to use other #PathVariables or #RequestParams, so passing title and description should be possible.
I used it to upload multiple images with AngularJS and FileUploader
( angular-file-upload v1.1.5 )
like this
var uploader = new FileUploader({
url: config.apiUrl('/machine/' + $scope.id + '/images/'),
method: "post",
queueLimit: maxFiles
});

Categories

Resources