Spring mvc upload multiple files at once with AJAX doesn't work - ajax

I'm using Spring boot 2.0.1 and I'm trying to upload multiple files with dropzone. Everything is working perfectly when I'm using uploadMultiple: false on Dropzone.js. When I set uploadMultiple: true, My Controller stops working.
The controller class is as follow:
#PostMapping(value = "/img/upload")
public ResponseEntity<?> fileUpload(#RequestParam("file") MultipartFile[] files){
System.out.println(files.length);
for (MultipartFile file : files) {
try {
file.transferTo(new File("/opt/img/" + file.getOriginalFilename()));
System.out.println(file.getOriginalFilename());
} catch (IOException e) {
e.printStackTrace();
}
}
return new ResponseEntity<>("File Uploaded Successfully.", HttpStatus.OK);
}
The files are no more than 1MB and my settings are
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
My request header when I upload the files:
------WebKitFormBoundaryihPcX9WHR5UA9jGD
Content-Disposition: form-data; name="file[0]"; filename="cars-02-01.png"
Content-Type: image/png
------WebKitFormBoundaryihPcX9WHR5UA9jGD
Content-Disposition: form-data; name="file[1]"; filename="Screenshot from 2018-05-03 23-31-53.jpg"
Content-Type: image/jpeg
Everything seems perfect. I still cannot find the reason for this problem?

It seems that I should use the MultipartHttpServletRequest instead of MultipartFile[] files. I Changed the method to:
#PostMapping(value = "/img/upload")
public ResponseEntity<?> fileUpload(MultipartHttpServletRequest request) {
Map<String, MultipartFile> fileMap = request.getFileMap();
for (MultipartFile file : fileMap.values()) {
try {
file.transferTo(new File("/opt/img/" + file.getOriginalFilename()));
System.out.println(file.getOriginalFilename());
} catch (IOException e) {
e.printStackTrace();
}
}
return new ResponseEntity<>("File Uploaded Successfully.", HttpStatus.OK);
}

Related

Spring boot RestTemplate upload file to SharePoint online but file is corrupted

There is a RestController and I try to upload a MultiPartFile to SharePointOnline using, the SharePoint REST API I'm also using proxy due to corporate restrictions.
#Override
public ResponseEntity uploadFile(MultipartFile file) throws ApiException, IOException {
RestTemplate restTemplate = createBasicRestTemplate();
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file",file.getResource());
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<MultiValueMap<String, Object>> uploadBodyEntity = new HttpEntity<>(body, header);
ResponseEntity<String> response = restTemplate.exchange(BASE_URL, HttpMethod.POST,
uploadBodyEntity, String.class);
return response;
}
public RestTemplate createBasicRestTemplate() {
RestTemplate restTemplate = new RestTemplateBuilder(new ProxyCustomizer()).build();
return restTemplate;
}
#Override
public void customize(RestTemplate restTemplate) {
HttpHost proxy = new HttpHost(PROXY_HOST, PROXY_PORT);
HttpClient httpClient = HttpClientBuilder.create()
.setRoutePlanner(new DefaultProxyRoutePlanner(proxy) {
#Override
public HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
return super.determineProxy(target, request, context);
}
})
.build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
The file upload is success, but it's cannot be opened. For example if upload a txt it will looks like this:
--raF_ORlUJptia2_av7ppLBeeMcGf5BUr
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
Content-Length: 159
--38dc5323d6b92b5c14c33fade0178306
Content-Disposition: form-data; name="file"; filename="test.txt"
blablalblalalal
--38dc5323d6b92b5c14c33fade0178306--
--raF_ORlUJptia2_av7ppLBeeMcGf5BUr--
If I upload an xlsx it's simply just not open, it shows 'File Format and Extension Don't Match' error.
I try to convert the MultiPartFile to simple File with this method:
public File convertFile(MultipartFile file) {
File convFile = new File(file.getOriginalFilename());
try {
convFile.createNewFile();
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
return convFile;
}
and change the controller to:
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
body.add("file",convertFile(file));
But the same thing happens.
How can I upload file with RestTemplate?
This is a sample request to the SharePoint REST API and based on documentation the endpoint should receive a array buffer
POST https://{site_url}/_api/web/GetFolderByServerRelativeUrl('/Folder Name')/Files/add(url='a.txt',overwrite=true)
Authorization: "Bearer " + accessToken
Content-Length: {length of request body as integer}
X-RequestDigest: "{form_digest_value}"
"Contents of file"
This is what i can see in the https log: http log
Solution was to remove MultiValueMap and replace with:
HttpEntity<byte[]> entity = new HttpEntity<>(file.getBytes(), spoHelperService.createAuthHeader(authToken));
ResponseEntity<SpoUploadResponse> response = restTemplate.exchange(uploadFileUrl, HttpMethod.POST,
entity, SpoUploadResponse.class);

Springboot Required request part 'file' is not present

I am working on a file upload controller and I am currently getting the following error when testing in Postman.
{
"timestamp": "2019-04-18T14:53:07.988+0000",
"status": 400,
"error": "Bad Request",
"message": "Required request part 'file' is not present",
"path": "/upload"
}
At the moment my controller is very simple but first I need to overcome this problem.
I have looked at the answers given
[here](upload file springboot Required request part 'file' is not present"upload file springboot Required request part file is not present")!
But unfortunately, anything suggested here did not resolve my problem
Any help with this error would be appreciated
This is my controller:
#Controller
public class UploadController {
#ResponseBody
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public boolean upload(#RequestParam("file") MultipartFile file) throws IOException {
try {
if (!file.isEmpty()) {
return true;
} else {
return false;
}
}
catch(Exception e){
e.printStackTrace();
return false;
}
}
}
It's difficult without knowing how you are sending the data but here's how i solved sending multipart/form-data through a #RestController:
#PostMapping(value = "/foo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
ResponseEntity fileUpload(#Requestparam("bar") LinkedList<MultipartFile> payload) {
MultipartFile file = payload.get(0)
...
Spring just wouldn't accept anything another than a linked list in my case, but that was form-data sent as an Angular2+ FormData object with field name bar.
As you hasve not mentioned your request model, let it be EarningRequest, so know your model data is:
class EarningRequest{
private FilePart file;
//and other data which you want to add.
//add the getter setters also, so that jackson can map the json to this pojo
}
#RestController
public class UploadController {
#PostMapping(value = "/upload",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public boolean upload (#ModelAttribute EarningRequest earningRequest){
//earningRequest contains the file
//you can get the filePart as earningRequest.getFile()
return true;
}
}
In postman under "key" I wasn't setting anything. I needed to set this as 'file'. I previously made the assumption all I had to do was click the drop-down and select file.
I will include below all the updated code & a link to the image which explains this better(I couldn't display image here as reputation < 10)
link to postman Image
#RestController
public class UploadController {
#PostMapping("/upload")
#ResponseBody
public boolean upload(#RequestParam("file") MultipartFile file) {
try{
if(file.isEmpty() ==false){
System.out.println("Successfully Uploaded: "+ file.getOriginalFilename());
return true;
}
else{
System.out.println("ERROR");
return false;
}
}
catch(Exception e){
System.out.println(e);
return false;
}
}
}

from andriod i am trying to upload image and i am using web services in java

below is the android part
new MultipartUploadRequest(this,uploadid,UPLOAD_URL)
.addFileToUpload(path,"image")
.addParameter("name",name)
.setNotificationConfig(new UploadNotificationConfig())
.setMaxRetries(2)
.startUpload();
below is my java controller in web services
#RequestMapping(value = "/uploadm",method=RequestMethod.POST)
public void submitQuestionuploading(#RequestBody String image) throws Exception
{
System.out.println(1+""+image);
try {
byte[] bytes = image.getBytes();
System.out.println(11);
BufferedOutputStream stream =new BufferedOutputStream(new
FileOutputStream(new File(UPLOAD_DIRECTORY +"11.png")));
stream.write(bytes);
stream.flush();
stream.close();
}
catch (Exception e) {
System.out.println(e);
}
output is this one i got in console but file is created but it is corrupted and it s size 0bytes ,
---------AndroidUploadService1518510071115 Content-Disposition: form-data; name="image"; filename="IMG_20180211_000033.jpg"
Content-Type: image/jpeg
ÿØÿá3ØExif
i tried to put this in java controller but it is not working
#RequestMapping(value = "/upload", method = RequestMethod.POST ,
headers = "Content-Type=multipart/form-data") public String
fileUpload(#RequestParam("image") CommonsMultipartFile file) {}
but i want to do in spring MVC only, help me to take uploaded file
This is a working file uploader
#ResponseStatus(code = HttpStatus.CREATED)
#RequestMapping(value = "asset", method = RequestMethod.POST, consumes = {
MediaType.MULTIPART_FORM_DATA_VALUE}, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
#ResponseBody
public String uploadImage(
#RequestParam("image") MultipartFile file) {
byte[] bytes = file.getBytes();
//do something with byte
return "ok or anything you want to return";
}
And also you need to register MultipartResolver as a depandency.
#Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(100000);
return multipartResolver;
}
you can deploy this code and then test using postman.
there are various tutorials for this.
you may have a look at
http://www.baeldung.com/spring-file-upload
https://www.boraji.com/spring-4-mvc-file-upload-example-with-commons-fileupload

IE image not getting loaded with X-Content-Type-Options:nosniff

Intro
I have spring MVC application I'm loading image from controller. For security purpose, I added X-Content-Type-Options:nosniff to my Spring application
By setting the following in springConfig xml <security:content-type-options/>
Problem : after this IE is not loading the images responded by controller. I suspect the content type is not set in the response. Because another site which is responding X-Content-Type-Options:nosniff and Content-Type:image/png; is working fine.
TRY1
I tried to change my controller to set content type. But it is not happening.
#RequestMapping(value = "/getUserImage" , produces = org.springframework.http.MediaType.IMAGE_PNG_VALUE)
public #ResponseBody
void getUserImage(
#RequestParam(value = "userId", required = false) int userId,
HttpServletRequest request, HttpServletResponse response) {
try {
//Get file and add it to response
IOUtils.copy(inputStream, response.getOutputStream());
response.getOutputStream().flush();
response.setContentType(org.springframework.http.MediaType.IMAGE_PNG_VALUE);
response.setHeader("Content-Type","image/png");
response.flushBuffer();
inputStream.close();
} catch (Exception e){
}
}
TRY2
I tried to add response header as the same way in method interceptor but still no luck.
But the same thing working in Chrome and Firefox.
Try this :
#RequestMapping(value = "/image/{personId}")
#ResponseBody
public HttpEntity<byte[]> getPhoto(#PathVariable int personId) {
Person person = this.personService.getPersonById(personId);
if (person != null && person.getProfileThumbnail() != null) {
try {
byte[] image;
try {
image = org.apache.commons.io.FileUtils.readFileToByteArray(new File(msg + "/" + person.getUsername() + "/" + personId + ".png"));
} catch (FileNotFoundException e) {
image = org.apache.commons.io.FileUtils.readFileToByteArray(new File(defaultProfilePath));
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
headers.setContentLength(image.length);
return new HttpEntity<>(image, headers);
} catch (IOException ignored) {
}
}
}
What I am basically doing is checking if there is an image on File-system for the user, if not then I am loading a default image. Right now it works on all browser, so even if personid is 0, I get default image back, with the else cause, which I have not posted here.

Getting No Response When Calling WebAPI Post with application/json header

I've got a very simple WebAPI controller (all system defaults) and when I do a post to it, the fact that it has Content-Type: application/json makes the post (from fiddler) hang (not return).
My headers are as follows:
Content-Length: 2
Content-Type: application/json
and the post body is simply
[]
My WebAPI controller just looks like this:
namespace WebAPI.rest
{
public class SendGridController : ApiController
{
public HttpResponseMessage Post()
{
try
{
HttpContent requestContent = Request.Content;
string json = requestContent.ReadAsStringAsync().Result.Trim();
}
catch (Exception ex)
{
throw ex;
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
When I make the same post (with fiddler) to http://respondto.it/ it returns no problem
If you are running under ASP.NET the the .Result is probably not a wise idea. I ran your code under self-host and it worked fine.
Try this,
public class SendGridController : ApiController
{
public async Task<HttpResponseMessage> Post()
{
try
{
HttpContent requestContent = Request.Content;
string json = await requestContent.ReadAsStringAsync();
}
catch (Exception ex)
{
throw ex;
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
}
The problem turned out to be an old version of webapi. Once I updated to webapi2, the problem went away.

Resources