有两种方式, 第一种是在前端直接上传文件到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 

  1. 登录OBS Console后在桶列表中,单击待操作的桶,进入“概览”页面;
  2. 在“基础配置”下,单击“CORS规则”卡片,进入“CORS规则”界面,如下图所示:

  3. 在“CORS规则”界面,单击“创建”,系统弹出“创建CORS规则”对话框,在该对话框中按照上表的参数进行配置,如下图所示:

  4. 单击“确定”,并在“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("上传失败");
    }

结束

Logo

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

更多推荐