有两种方式, 第一种是在前端直接上传文件到obs, 第二种是先把文件上传到后台, 然后后台再调用obs对应开发语言的SDK
1. 前端直接上传文件到obs,不经过后端
1.1 使用npm引入包
// 安装 npm i esdk-obs-browserjs // 引入 import * as ObsClient from 'esdk-obs-browserjs'
1.2 上传方法
uploadObs() {
// 创建ObsClient实例
var obsClient = new ObsClient({
access_key_id: 'xxx', // 你的ak
secret_access_key: 'xxx', // 你的sk
server: 'https://xxx.com' // 你的endPoint
})
obsClient.putObject({
Bucket: 'xxx', // 桶名
Key: this.path + 'test01.jpg', // 路径 + 文件名
SourceFile: document.getElementById('input-file').files[0]
}, function (err, result) {
if (err) {
console.error('Error-->' + err)
} else {
console.log('Status-->' + result.CommonMsg.Status)
}
})
},
new ObsClient时报错
Error in v-on handler: "TypeError: _huaweiobs_esdk_obs_browserjs_3_22_3_min_
解决办法:
页面的import改为:
import ObsClient from 'esdk-obs-browserjs/src/obs'
此时如果报以下错误
Access to XMLHttpRequest at 'https://xxx.obs.cn-north-4.myhuaweicloud.com/?apiversion' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
则是跨域问题
解决办法:
配置桶的CORS
- 登录OBS Console后在桶列表中,单击待操作的桶,进入“概览”页面;
- 在“基础配置”下,单击“CORS规则”卡片,进入“CORS规则”界面,如下图所示:
- 在“CORS规则”界面,单击“创建”,系统弹出“创建CORS规则”对话框,在该对话框中按照上表的参数进行配置,如下图所示:
- 单击“确定”,并在“CORS规则”界面查看已配置好的规则。
说明:
桶的CORS配置会在两分钟内生效,生效后才能使用OBS BrowserJS SDK访问桶。
参考官方文档: 配置桶的CORS_对象存储服务 OBS_BrowserJS_初始化_华为云
如果是使用element-ui的el-upload上传组件,则定义:http-request属性即可
1.3 获取上传进度
同时SDK提供获取上传进度的回调 ProgressCallback
示例代码:
// 创建ObsClient实例
var obsClient = new ObsClient({
access_key_id: '*** Provide your Access Key ***',
secret_access_key: '*** Provide your Secret Key ***',
server : 'https://your-endpoint'
});
var callback = function(transferredAmount, totalAmount, totalSeconds){
// 获取上传平均速率(KB/S)
console.log(transferredAmount * 1.0 / totalSeconds / 1024);
// 获取上传进度百分比
console.log(transferredAmount * 100.0 / totalAmount);
// 百分比取整数
console.log(Math.floor(transferredAmount * 100.0 / totalAmount))
};
obsClient.putObject({
Bucket : 'bucketname',
Key : 'objectname',
SourceFile : document.getElementById('input-file').files[0],
ProgressCallback: callback
}, function (err, result) {
if(err){
console.error('Error-->' + err);
}else{
console.log('Status-->' + result.CommonMsg.Status);
}
});
配合element-ui的el-progress组件, 即可显示上传进度
参考官方文档: 获取上传进度_对象存储服务 OBS_BrowserJS_上传对象_华为云
1.4 文件访问地址
browserjs的sdk在上传的回调中没有返回文件访问地址, 所以我们可以自己进行拼接
'https://' + bucket + '.obs.cn-north-4.myhuaweicloud.com/' + key
bucket是桶名, bucket后面的字符串是 endPoint, 一般endPoint是
https://obs.cn-north-4.myhuaweicloud.com
去掉https即可. 最后的key则是文件名, 或文件路径+文件名
2. 先上传到后端,然后再上传到obs
2.1 前端代码:
这里用的vue + element-ui
js:
// 文件上传成功后触发的函数
handleAvatarSuccess: function (res, file) {
console.log('文件上传成功')
console.log(res)
this.dataItem.picture = res.data
this.imageUrl = res.data
console.log(res.data)
},
// 文件上传失败后触发的函数
handleAvatarError: function (res, file) {
if (res.errorCode) {
this.$message.error(res.errorMsg)
} else {
this.$message.error('文件上传失败')
}
},
beforeAvatarUpload: function (file) {
const isJPG = (file.type === 'image/jpg' || file.type === 'image/jpeg' || file.type === 'image/png')
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!')
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
return isJPG && isLt2M
},
// 上传进度
uploadAvatarProcess(event, file, fileList) {
this.videoFlag = true
console.log(typeof (file.percentage.toFixed(0)))
this.videoUploadPercent = Math.floor(event.percent)
},
html:
<el-form-item label="图片:">
<el-upload class="avatar-uploader"
:action="imgAction"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:on-error="handleAvatarError"
:on-progress="uploadAvatarProcess"
name='file'
:data="imgpath"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
2.2 后端代码
这里后端用的是java, springboot框架
maven依赖:
<!-- 华为云obs -->
<dependency>
<groupId>com.huaweicloud</groupId>
<artifactId>esdk-obs-java</artifactId>
<!-- 下面的设置是为了获取最新obs的maven最新版本号, 但是新版本的okhttp3会和别的依赖冲突,所以就指定了一个不会冲突的版本 -->
<!-- <version>[3.20.6.1,)</version>-->
<version>3.20.6.1</version>
</dependency>
后端上传接口代码:
/**
* 上传文件到obs
*
* @param path 服务器端存储的路径
* @param file 服务器商存储的文件名称
* @return
*/
@ApiOperation(value = "上传文件到obs", notes = "上传文件到obs")
@PostMapping(value = "/upload")
@ResponseBody
public Response upload(@ApiParam(name = "path", value = "obs存储路径") @RequestParam(value = "path") String path,
@ApiParam(name = "file", value = "文件") @RequestParam(value = "file") MultipartFile file) {
Long userId = httpServletRequest.getHeader(Constants.USER_ID) != null ? Long.parseLong(httpServletRequest.getHeader(Constants.USER_ID)) : 1L;
LogGenerator.genLog(
httpServletRequest,
userId, LogConstants.HUA_WEI_CLOUD_OBS.UPLOAD,
path
);
System.out.println("正在请求 obs / upload 上传文件接口----------------");
System.out.println("文件大小: " + ByteUtils.byteFormatString(file.getSize()));
long startTime = System.currentTimeMillis();
ObsClient obsClient;
try {
// 用UUID命名文件
String fileName = UUIDUtil.getUUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
// 服务器临时路径
String targetPath = imgpath + fileName;
System.out.println("服务器图片路径: " + targetPath);
File tempImg = new File(targetPath);
// 先上传到服务器
file.transferTo(tempImg);
String accountName = env.getProperty("HWObs.HWAccountName");
String name = env.getProperty("HWObs.HWUsername");
String password = env.getProperty("HWObs.HWPassword");
String projectName = env.getProperty("HWObs.HWProjectName");
String token = ObsUtils.getToken(accountName, name, password, projectName);
if (token == null || token.length() <= 0) {
return Response.failure("token解析错误");
}
String result = ObsUtils.getSecurityToken(token);
if (StringUtils.isBlank(result)) {
return Response.failure("securityToken解析错误");
}
CredentialDto credentialDto = JSONObject.parseObject(result, CredentialDto.class);
if (credentialDto == null) {
return Response.failure("securityToken返回值解析错误");
}
String ak = credentialDto.getCredential().getAccess();
String sk = credentialDto.getCredential().getSecret();
String securitytoken = credentialDto.getCredential().getSecuritytoken();
// System.out.println("ak: " + ak);
// System.out.println("sk: " + sk);
// System.out.println("securitytoken: " + securitytoken);
String endPoint = env.getProperty("HWObs.HWEndPoint");
// 创建ObsClient实例
obsClient = new ObsClient(ak, sk, securitytoken, endPoint);
String bucketName = env.getProperty("HWObs.HWBucketName");
PutObjectResult putObjectResult = obsClient.putObject(bucketName, path + fileName, tempImg); // localfile为待上传的本地文件路径,需要指定到具体的文件名
if (putObjectResult == null) {
return Response.failure("上传失败");
}
System.out.println("上传obs成功: " + putObjectResult.getObjectUrl());
// 删除临时文件
boolean deleteResult = tempImg.delete();
System.out.println("临时文件删除结果: " + deleteResult);
long endTime = System.currentTimeMillis();
System.out.println("耗时: " + ((endTime - startTime) / 1000) + "秒");
return new Response(putObjectResult.getObjectUrl());
} catch (Exception e) {
e.printStackTrace();
}
return Response.failure("上传失败");
}
结束