四.minio前端获取签名地址直传minio文件服务器(前端直传)
1.概述2.前端直接
目录
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状态码即表示上传成功
更多推荐
所有评论(0)