
【前端】Java端提供签名,vue elementUI axios直传文件至OSS(带进度条)
·
前言:
- 记得在OSS中配置bucket的跨域设置。
- 该方法只适用5G以内的文件,如果超大文件需要分片上传。
- 带上传进度条。
java代码(包含后端上传文件、删除文件、提供签名)
{
private final static String OSS_BUCKET_NAME = "test";
private final static String ENDPOINT_URL = "oss-cn-beijing.aliyuncs.com";
private final static String OSS_ACCESS_DOMAIN_URL = "https://"+OSS_BUCKET_NAME+"."+ENDPOINT_URL;
private final static String ACCESS_KEY_ID = "你自己的keyid";
private final static String ACCESS_KEY_SECRET = "你自己的key secret";
// 自定义的文件夹名(注意:第一位字符 不能是 / 否则oss端会报错)
private final static String UPLOAD_DIR = "upload/";
public static OSSClient initClient(){
return new OSSClient(ENDPOINT_URL, CredentialsProviderFactory.newDefaultCredentialProvider(ACCESS_KEY_ID, ACCESS_KEY_SECRET),
new ClientConfiguration());
}
/**
* [描述] 提供令牌给前端 让前端直传到OSS
*/
public static Object getSignature() {
OSSClient ossClient = initClient();
//token 过期时间(分钟)
long expireTime = 10;
long expireEndTime = System.currentTimeMillis() + expireTime *1000;
Date expiration = new Date(expireEndTime);
//生成的到期时间转换位s,并转换为String
String expire = String.valueOf(expireEndTime / 1000);
//构造用户表单域Policy条件
PolicyConditions policyCond = new PolicyConditions();
//设置上传文件大小的范围
policyCond.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
//设置上传的路径的前缀:就是上传到指定文件夹
policyCond.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, UPLOAD_DIR);
//根据到期时间生成policy策略
String postPolicy = ossClient.generatePostPolicy(expiration, policyCond);
//对policy进行UTF-8编码后转base64
byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
String endPolicy = BinaryUtil.toBase64String(binaryData);
//生成签名,policy表单域作为填入的值,将该值作为将要签名的字符串。
String signature = ossClient.calculatePostSignature(postPolicy);
//封装参数参数返回
HashMap<String, Object> map = new HashMap<>(5);
map.put("OSSAccessKeyId",ACCESS_KEY_ID);
map.put("host",OSS_ACCESS_DOMAIN_URL);
map.put("policy",endPolicy);
map.put("signature",signature);
map.put("expiration",expire );
map.put("key",UPLOAD_DIR );
map.put("success_action_status","200");
map.put("msg","签名成功");
return map;
}
/**
* 获取随机文件名用来保存
* @param fileName 用户文件名称
* @return 实际的cos上文件名称
*/
private static String getRealFileName(String saveFolder, String fileName) {
return StringUtils.isNotEmpty(saveFolder) ? saveFolder + "/" + fileName : fileName;
}
public static String upload(String saveFolder, String contentType, String fileName, long contentLength, InputStream input) {
if (StringUtils.isEmpty(fileName) || StringUtils.isEmpty(contentType) || contentLength <= 0 || null == input) {
return null;
}
ObjectMetadata objectMeta = new ObjectMetadata();
objectMeta.setContentLength(contentLength);
objectMeta.setContentType(contentType);
String filePath = getRealFileName(saveFolder, fileName);
try {
initClient().putObject(OSS_BUCKET_NAME, filePath, input, objectMeta);
return OSS_ACCESS_DOMAIN_URL + filePath;
} catch (Exception e) {
e.printStackTrace();
logger.error(e.getMessage(),e);
return null;
} finally {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
logger.error(e.getMessage(),e);
}
}
}
/**
* 前端把文件上传给后端 后端再上传至OSS
*/
public static String upload(String saveFolder, MultipartFile multipartFile) {
if(multipartFile == null || multipartFile.isEmpty()){
return null;
}
try {
String fileMainName = System.currentTimeMillis()+"-";
String filename = multipartFile.getOriginalFilename();
String extFileName;
if (StringUtils.isNotEmpty(filename)) {
extFileName = filename.substring(filename.lastIndexOf("."));
} else {
extFileName = ".jpg";
}
return upload(saveFolder, multipartFile.getContentType(), fileMainName + extFileName, multipartFile.getSize(), multipartFile.getInputStream());
} catch (IOException e) {
e.printStackTrace();
logger.error(e.getMessage(),e);
return null;
}
}
/**
* 通过url地址删除指定文件
*/
public static void delete(String fileUrl) {
if (StringUtils.isEmpty(fileUrl)) {
return;
}
try {
fileUrl = fileUrl.replaceFirst(OSS_ACCESS_DOMAIN_URL, "");
initClient().deleteObject(OSS_BUCKET_NAME, fileUrl);
} catch (OSSException | ClientException e) {
e.printStackTrace();
logger.error(e.getMessage(),e);
}
}
}
前端VUE代码
<template>
<div>
<el-upload
class="upload-demo"
ref="upload"
action="#"
:on-preview="handlePreview"
:on-remove="handleRemove"
:on-change="handleChange"
:auto-upload="false"
>
<el-button slot="trigger" size="small" type="primary">
选取文件
</el-button>
<el-button
style="margin-left: 10px"
size="small"
type="success"
@click="submitUpload"
>
上传到服务器
</el-button>
<div slot="tip" class="el-upload__tip">
只能上传jpg/png文件,且不超过500kb
</div>
</el-upload>
<div style="width: 30%">
<el-progress :percentage="percent"></el-progress>
</div>
<div>
<el-image style="width: 200px" :src="url"></el-image>
</div>
</div>
</template>
<script>
import uploadUtil from '/request/uploadUtil'
export default {
data() {
return {
file: null,
percent: 0,
}
},
components: {},
methods: {
submitUpload() {
this.percent = 0
const result = uploadUtil.startUpload2(
this.file,
(progressEvent) => {
this.percent =
(progressEvent.loaded / progressEvent.total) * 100 || 0
}
)
result.then((res) => {
console.log(res)
this.url = res.fileUrl
this.percent = 100
})
},
handleRemove(file, fileList) {
console.log(file, fileList)
},
handlePreview(file) {
this.openVideoPlyer = true
this.videoFile = file
},
handleChange(file, fileList) {
if (fileList.length > 1) {
fileList.splice(0, 1)
}
this.file = file
},
},
}
</script>
upload.js 工具类:
import axios from "axios"
import { Message } from 'element-ui';
// bucket 名
const fdBucket = 'jg';
// 获取oss上传签名
const getOssTokenUrl = '/oss/get_oss_token';
async function startUpload2(file, coolDown,) {
let res= {};
await axios.get(getOssTokenUrl, { 'fileScene': fdBucket, 'fileName': file.name })
.then((result) => {
res = result.data;
})
const formData = new FormData();
formData.append("OSSAccessKeyId", res.accessKeyId);
formData.append("key", res.filePath);
formData.append("policy", res.policy);
formData.append("signature", res.signature);
// 注意:file文件必须放在表单的最后面,OSS官网有说明
formData.append("file", file.raw ? file.raw : file);
return await axios({
url: res.host,
timeout: 1000 * 60 * 10,
method: 'post',
data: formData,
headers: { 'Content-Type': 'multipart/form-data' },
onUploadProgress: function (progressEvent) {
if (progressEvent.lengthComputable) {
coolDown(progressEvent);
}
},
}).then(() => {
return { 'fileUrl': res.fileUrl, 'filePath': res.filePath };
}).catch(() => {
Message.error('上传失败,请联系管理员');
return { 'fileUrl': '', 'filePath': '' };
});
}
export default { startUpload2 }
postman 上传文件测试截图:
OSS官网文档地址:
https://help.aliyun.com/document_detail/605225.html?spm=a2c4g.475682.0.0.4d686dd4C9tKE8
https://help.aliyun.com/document_detail/605224.html?spm=a2c4g.605225.0.0.7ddb7aabQxkDv
参考博客:
https://blog.csdn.net/weixin_42681295/article/details/121156732
更多推荐
所有评论(0)