目录

1.概述

1.1.需求

1.2.问题

1.3问题解决

2.java生成签名地址,前端直接传

java生成地址

html上传文件代码

3.通过后端接口获取上传地址再上传

4.axios+element

5.上传成功反馈


gitee:https://gitee.com/pythonloser/springboot-minio/tree/master

一.minio安装与使用:https://blog.csdn.net/xixiyuguang/article/details/119344480

二.minio整合springboot、文件上传下载、增删改查bucket和object:https://blog.csdn.net/xixiyuguang/article/details/119447614

三.minio 的分布式部署、单节点多磁盘、多节点模式:https://blog.csdn.net/xixiyuguang/article/details/119456729

四.minio前端获取签名地址直传minio文件服务器(前端直传):https://blog.csdn.net/xixiyuguang/article/details/119571051

1.概述

1.1.需求

        后端生成presigned url(预签名url,里面包含上传到AWS S3所需要的一些认证标识信息)给到前端,前端通过这个URL将文件上传到云服务上。

        类似阿里云OSS的获取签名直传。

1.2.问题

        上传成功后发现,上传的文件打不开。(上传对象为new Formdata(文件对象))

问题解释

参考:https://blog.csdn.net/yujin0213/article/details/88602616

        一般图片、文件上传都是使用FormData对象传递二进制文件,但是上传完之后,下载后的图片无法打开,将其二进制数据与原文件二级制数进行对比,发现有额外的二进制数据

        后来在github上找到了解决方案,原来使FormData对象上传文件到上会损坏原文件的二进制数据,直接上传文件对象就行

1.3问题解决

github:https://github.com/aws/aws-sdk-js/issues/547

2.java生成签名地址,前端直接传

java生成地址

http://127.0.0.1:9090/product/1.png?response-content-type=application%2Fjson&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20210810%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210810T040847Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=fc64acd9e68a7fa91669dda70018d70e10dbe09597932285c7223255e5377574


public class PresignedPutObjectUrl {
    public static void main(String[] args) {
        try {

            MinioClient minioClient = MinioClient.builder().endpoint("http://127.0.0.1:9090")
                    .credentials("admin", "12345678").build();
            Map<String, String> reqParams = new HashMap<String, String>();
            reqParams.put("response-content-type", "application/json");
            String product = minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.PUT) //这里必须是PUT,如果是GET的话就是文件访问地址了。如果是POST上传会报错.
                            .bucket("product")
                            .object("1.png")
                            .expiry(60 * 60 * 24)
                            .extraQueryParams(reqParams)
                            .build());
            System.out.println(product); // 前端直传需要的url地址
        } catch (Exception e) {
            System.out.println("Error occurred: " + e);
        }
    }
}

html上传文件代码

<!DOCTYPE html>
<html>
  <head lang="en">
    <meta charset="UTF-8" />
    <script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>
    <title></title>
  </head>
  <body>
    <form id="uploadForm"  >
      姓名:<input id="name" type="text" name="name" /> <br /><br />
      性别:<input id="sex" type="text" name="sex" /> <br /><br />
      文件:<input id="file" type="file" name="file" />
      <input type="submit" value="提交 submit" />
    </form>
   
  </body>
  <script type="text/javascript">
    $(function () {

      var putUrl = "http://127.0.0.1:9090/product/1.png?response-content-type=application%2Fjson&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20210810%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210810T040847Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=fc64acd9e68a7fa91669dda70018d70e10dbe09597932285c7223255e5377574";
      //监听表单提交,变为异步提交表单
      $("#uploadForm").on("submit", function (event) {
        var form = this; //this代表的就是当前提交表单的DOM对象
        //用H5的FormData对象对表单数据进行构造

        console.log($('#file'))
        console.log($('#file')[0].files[0])

        $.ajax({
          url: putUrl,
          type: "put",
          // data:  $('#uploadForm')[0][2].files[0], //直接将文件对象传输
          data:  $('#file')[0].files[0], //直接将文件对象传输
          dataType: "JSON",
          async: true,
          //要想用jquery的ajax来提交FormData数据,
          //则必须要把这两项设为false
          processData: false,
          contentType: false,
          error: function (xhr, status, error) {
            alert("请求出错!");
          },
          success: function (result) {
            alert("表单提交成功!");
          },
        });
        //阻止表单的提交事件
        return false;
      });
     
    });
  </script>
</html>

3.通过后端接口获取上传地址再上传

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8" />
    <script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>
    <title></title>
</head>

<body>
    <form id="uploadForm" enctype="multipart/form-data">
        文件: <input id="file" type="file" name="file" />
    </form>
    <button id="upload">上传文件</button>
</body>
<script type="text/javascript">
    $(function() {
        $("#upload").click(function() {
            var getPresignedUrl =
                "http://localhost:8080/xxx/minio/getPresignedUrl?bucketName=product&objectName="+$('#file')[0].files[0].name;

            // todo 先获取上传的签名的url
            $.ajax({
                    type: "get",
                    url: getPresignedUrl, //上传文件的请求路径必须是绝对路劲
                    data: {},
                })
                .success(function(response) {
                    console.log(response);
                    if (response.httpCode === 200) {
                        var uploadPutUrl = response.data;
                        // todo 通过签名的url上传文件
                        $.ajax({
                                type: "put",
                                url: uploadPutUrl, //上传文件的请求路径必须是绝对路劲
                                data: $('#file')[0].files[0], //直接上传文件对象
                                cache: false,
                                processData: false, //因为data值是FormData对象,不需要对数据做处理。
                                contentType: false, //因为是由<form>表单构造的FormData对象,所以这里设置为false。
                            })
                            .success(function(response) {
								// success 即成功
                                console.log(response);
                            })
                            .error(function() {
								// error 即失败
                                alert("上传失败");
                            });
                    } else {
                        alert("失败");
                    }
                })
                .error(function() {
                    alert("失败");
                });
        });
    });
</script>

</html>

4.axios+element

参考:https://blog.csdn.net/yujin0213/article/details/88602616

 <el-upload
     class="avatar-uploader"
     action="123"
    :http-request="upload"
    :before-upload="beforeAvatarUpload">
    <img v-if="params.defaultImgUrl" :src="params.defaultImgUrl" class="avatar">
    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>

upload(res)
{
    let file = res.file;  //注意:直接上传file文件,不要用FormData对象的形式传
    let config = {
        headers: {
            'Content-Type': 'multipart/form-data'
        }
    };
    //从接口获取presigned url
    getUploadUrl({uploadType: 6}).then(res => {
        let result = res.data;

        if (result.code === 0) {
            const info = JSON.parse(result.msg);
            //需要用put方法上传,post会报405,aws官方规定是put方法
            axios.put(info.presignedUrl, file, config)
                .then(res => {
                    if (res.status == 200) {
                        this.params.defaultImgUrl = info.cdnUrl;
                    }
                }).catch(
                err => {
                    console.log(err)
                }
            )
        }
    }).catch(err => {
        console.log('get upload info', err)
    })
}

5.上传成功反馈

返回200状态码即表示上传成功

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐