如何从React前端通过Spring后端将文件上传到S3存储桶?

时间:2019-06-03 19:23:47

标签: java spring reactjs spring-boot amazon-s3

我正在尝试通过React将文件上传到s3存储桶,并且我在4xx和5xx方面苦苦挣扎:(

这是我的代码库:

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} />
    );
}

如果我发送此帖子,我将得到500和此错误:

java.io.IOException:UT000036:连接终止,无法解析多部分数据

我还注意到文档属性为空:

file

这是后端的API文档:

doc

我该如何解决?也许,我需要以某种方式将文件本地转换为二进制数据等?我们可以上传图像和.pdf文件。

谢谢!

1 个答案:

答案 0 :(得分:1)

使用MultipartHttpServletRequest

非常简单

第1步:添加依赖项

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>

第2步:像上面发送邮件一样发送文件。

第3步:在配置文件中配置bean(我已经使用过基于Java的配置)

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

第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.");
        }

}

最好将图像保存在本地,因为如果需要经常使用s3存储桶,则每次都无法从s3存储桶中获取图像。