1

I am trying to upload file to the s3 bucket via React and I am struggling with 4xx and 5xx :(

Here is my code base:

onChangeHandler = event => {
    const data = new FormData();

    data.append('data', event.target.files[0], event.target.files[0].name);

    axios
        .post(
            '/api/attachments/temporary',
            {
                documents: data,
                tempDir: this.generateUuid()
            },
            {
                headers: {
                    'Content-Type': 'multipart/form-data'
                }
            }
        )
        .then(data => {
            console.log(`data --- `, data);
        })
        .catch(e => {
            console.log(` --- `, e);
        });
};

render() {
    return (
            <input type='file' name='file' onChange={this.onChangeHandler} />
    );
}

If I am sending this post I get 500 and this error:

java.io.IOException: UT000036: Connection terminated parsing multipart data

Also I have noticed that documents property is empty:

file

This is API doc for backend:

doc

How may I fix it? Maybe, I need somehow transform file locally into binary data etc.? We can upload images and .pdf files.

Thanks!

Nikita Shchypyplov
  • 1,090
  • 1
  • 9
  • 18
  • [this post](https://stackoverflow.com/questions/25699727/multipart-file-upload-spring-boot) should be helpful – Morteza Jalambadani Jun 03 '19 at 19:30
  • i believe the issue is that you are mixing json data with the file/ formData upload this might help -> https://stackoverflow.com/questions/30655582/uploading-files-and-json-data-in-the-same-request-with-jquery-ajax – Eric Hasselbring Jun 03 '19 at 19:39

1 Answers1

1

It's very easy if you use MultipartHttpServletRequest

Step 1: Add dependency

pom.xml

<dependency>
<groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>

Step 2:Send the file same like you are sending above.

Step 3: Configure bean in configuration file(I have used java based configuration)

@Bean(name = "multipartResolver")
    public CommonsMultipartResolver createMultipartResolver() {
        CommonsMultipartResolver resolver=new CommonsMultipartResolver();
        resolver.setDefaultEncoding("utf-8");
        return resolver;
    }

Step 4:

@RequestMapping(value="/api/attachments/temporary")
public ServiceResponse uploadFile(MultipartHttpServletRequest request){

if (request.getFileNames().hasNext()) {
            //1. get the files from the request object
            Iterator<String> itr = request.getFileNames();
            MultipartFile multipartFileImage = request.getFile(itr.next());
            StringBuilder sb=new StringBuilder(multipartFileImage.getOriginalFilename());

            String filename=sb.substring(sb.lastIndexOf("."), sb.length()); // getting file extension
            filename="("+email+")"+filename; // concatenation unique value i.e email to its file name with extension
            user.setProfileImage(filename);

        try {
            File saveImage = new File(imagePath+filename);  //Local path for image file

            PropertiesCredentials cred = new PropertiesCredentials(getClass().getClassLoader().getResourceAsStream(awsCredentialsProperties));
            logger.debug("Aws access key id :"+cred.getAWSAccessKeyId());
            logger.debug("Aws Secret key :"+cred.getAWSSecretKey());
            AWSCredentials credentials = new BasicAWSCredentials(cred.getAWSAccessKeyId(),
                      cred.getAWSSecretKey()
                    );

            AmazonS3 s3client = AmazonS3ClientBuilder
                      .standard()
                      .withCredentials(new AWSStaticCredentialsProvider(credentials))
                      .withRegion(#) // Your region
                      .build();

            PutObjectResult putResult = s3client.putObject(
                      "<bucket name>", 
                      filename, 
                      saveImage
                    );
            multipartFileImage.transferTo(saveImage);
            logger.debug("putResult :"+putResult.getVersionId());
        }catch(Exception e) {
            return ServiceResponse.createFailureResponse("Unable to upload image due to internet connection failure. Try again later.");
        }

}

It's better that you save your image locally because it's not feasible to get image everytime from s3 bucket if your image is demanding to be available frequently.

Kramer
  • 389
  • 8
  • 34