UniApp 全端兼容 OSS 视频上传实现方案

在 UniApp 开发中,视频上传是高频需求,而将视频直接上传至阿里云 OSS 能有效降低服务器压力、提升上传速度,本文将实现一套 ** 全端兼容(微信小程序 / APP/H5)** 的 UniApp 视频上传方案,包含视频选择、本地预览、OSS 直传、上传状态管理等核心功能,代码可直接复用。

一、前期准备工作

1 安装插件

javascript 复制代码
// 下面这3个信息必填
const url = 'https://xxx.oss-cn-beijing.aliyuncs.com/'
const OSSAccessKeyId = ''
const OssAccesskeySercet= '';

2 阿里云 OSS 配置

  • 拥有阿里云 OSS 存储空间,确保存储空间的跨域规则 配置正确(关键,解决 H5 / 小程序跨域问题):
    • 允许来源:*(测试环境,生产环境可配置具体域名)
    • 允许方法:GET、POST、PUT、DELETE
    • 允许头:*
    • 暴露头:ETag
    • 过期时间:3600
  • 获取 OSS 上传所需的密钥信息 (由后端提供,前端禁止硬编码 AccessKey ID/Secret,防止泄露):
    • bucket 名称
    • OSS 地域节点(如 oss-cn-hangzhou.aliyuncs.com
    • 后端签名接口(前端通过接口获取临时上传签名,而非直接使用永久密钥)

插件基础配置(可选)

若需统一配置 OSS 基础信息,可在 oss.js 中简单配置,或在调用上传方法时传入(推荐后端动态返回,更安全)。

二、完整实现代码

本次实现包含视频选择、本地预览、删除已选视频、OSS 直传、上传加载 / 失败提示等完整功能,适配全端,代码结构清晰,可直接集成到项目中。

1 模板部分(template)

html 复制代码
<template>
  <!-- 视频上传容器 -->
  <view class="video-upload-container">
    <view class="video-upload-input d-flex-cen1 nborder" style="flex-wrap: wrap;">
      <!-- 已选视频预览 -->
      <view class="iconfont-img video-preview" v-if="form.videoUrl">
        <!-- 视频预览(UniApp 全端兼容的视频标签) -->
        <video :src="form.videoUrl" mode="aspectFill" controls></video>
        <!-- 删除视频按钮 -->
        <view class="iconfont icon-shanchu3 video-delete" @tap="deleteVideo"></view>
      </view>
      <!-- 选择视频按钮(未选视频时显示) -->
      <view class="iconfont-img d-flex-cen2 video-add" @tap="addVideo" v-else>
        <view class="iconfont icon-dizhi-tianjia video-add-icon"></view>
        <text class="video-add-text">点击选择/拍摄视频</text>
      </view>
    </view>
  </view>
</template>
<script>
// 引入 OSS 上传核心方法
import { ossUpload } from "@/js_sdk/jason-alioss-upload/oss.js";

export default {
  name: "VideoOssUpload",
  data() {
    return {
      // 表单数据,存储视频 OSS 地址
      form: {
        videoUrl: ""
      }
    };
  },
  methods: {
    /**
     * 选择/拍摄视频并上传至 OSS
     */
    async addVideo() {
      const that = this;
      // 调用 UniApp 原生视频选择API,全端兼容
      uni.chooseVideo({
        sourceType: ["camera", "album"], // 支持相机拍摄、相册选择
        compressed: false, // 不压缩视频(如需压缩可设为true,根据业务需求调整)
        camera: "back", // 默认使用后置摄像头
        maxDuration: 60, // 视频最大时长,单位秒(可根据业务自定义)
        success: async (res) => {
          // 上传前显示加载提示,防止用户重复操作
          uni.showLoading({
            title: "视频上传中...",
            mask: true // 遮罩层,禁止背景操作
          });

          try {
            // 处理视频文件名:截取原文件名,防止特殊字符问题
            const pathArr = res.tempFilePath.split("/");
            const fileName = pathArr[pathArr.length - 1];
            // 拼接完整文件名(保留原后缀,防止OSS识别异常)
            const videoName = `${new Date().getTime()}-${fileName}`; // 加时间戳,避免文件名重复

            // 调用插件 OSS 上传方法,核心一步
            const { success, data } = await ossUpload(
              res.tempFilePath, // 视频临时文件路径(uni.chooseVideo 返回)
              videoName, // 上传至OSS的文件名
              "" // 可选:OSS 文件夹路径,如 "video/2026/",方便OSS文件管理
            );

            // 上传成功处理
            if (success) {
              uni.hideLoading();
              // 响应式更新视频OSS地址(必须用$set,确保数据双向绑定)
              that.$set(that.form, "videoUrl", data);
              uni.showToast({
                title: "视频上传成功",
                icon: "success",
                mask: true
              });
            }
          } catch (error) {
            // 捕获上传异常
            uni.hideLoading();
            console.error("视频上传异常:", error);
            uni.showToast({
              title: "视频上传失败,请重试",
              icon: "none",
              mask: true
            });
          }
        },
        fail: (err) => {
          // 选择视频失败处理(如用户取消选择、权限不足)
          console.error("选择视频失败:", err.errMsg);
          // 排除用户主动取消的情况,避免不必要的提示
          if (!err.errMsg.includes("cancel")) {
            uni.showToast({
              title: "选择视频失败",
              icon: "none",
              mask: true
            });
          }
        }
      });
    },

    /**
     * 删除已选视频
     */
    deleteVideo() {
      const that = this;
      uni.showModal({
        title: "提示",
        content: "确定要删除该视频吗?",
        success: (res) => {
          if (res.confirm) {
            // 清空视频OSS地址
            that.$set(that.form, "videoUrl", "");
          }
        }
      });
    }
  }
};
</script>
<style lang="scss" scoped>
// 基础布局混合器(复用)
@mixin d-flex-cen {
  display: flex;
  align-items: center;
  justify-content: center;
}

.video-upload-container {
  width: 100%;
  padding: 20rpx;
  box-sizing: border-box;
}

.video-upload-input {
  width: 100%;
  height: 300rpx;
  border: 1px dashed #e5e5e5;
  border-radius: 16rpx;
  box-sizing: border-box;
  padding: 20rpx;

  // 视频预览容器
  .video-preview {
    width: 100%;
    height: 100%;
    position: relative;
    border-radius: 12rpx;
    overflow: hidden;

    video {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }

    // 删除按钮
    .video-delete {
      position: absolute;
      top: -10rpx;
      right: -10rpx;
      width: 40rpx;
      height: 40rpx;
      background: #ff4444;
      color: #fff;
      border-radius: 50%;
      @include d-flex-cen;
      font-size: 24rpx;
      z-index: 10;
      box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.2);
    }
  }

  // 选择视频按钮
  .video-add {
    width: 100%;
    height: 100%;
    color: #999;
    flex-direction: column;
    gap: 16rpx;

    .video-add-icon {
      font-size: 60rpx;
    }

    .video-add-text {
      font-size: 28rpx;
    }

    &:active {
      background: #f5f5f5;
      border-radius: 12rpx;
    }
  }
}
</style>

三、全端兼容注意事项

1 、微信小程序端

  • 需在小程序后台配置 OSS 域名白名单:登录微信公众平台 → 开发 → 开发设置 → 服务器域名 → 添加上传 / 下载的 OSS 域名;
  • 小程序对临时文件有有效期限制,选择视频后建议立即上传,避免文件失效;
  • 相机 / 相册权限:UniApp 会自动向微信小程序申请权限,无需手动配置。

2 、App 端(iOS/Android)

  • 需在 manifest.json 中配置相机、相册、存储权限
    • iOS:在 iosplist 中添加 NSCameraUsageDescription(相机权限说明)、NSPhotoLibraryUsageDescription(相册权限说明);
    • Android:在 androidpermissions 中添加 CAMERAREAD_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE
  • App 端支持大视频上传,建议根据业务需求设置 compressed: true 压缩视频,提升上传速度。

3、H5 端

  • 确保阿里云 OSS 存储空间跨域规则配置正确(核心,否则会出现跨域报错);
  • H5 端对视频文件大小有浏览器限制,建议添加文件大小校验,示例:
javascript 复制代码
success: async (res) => {
  // 校验视频大小,限制500M以内
  if (res.size > 500 * 1024 * 1024) {
    uni.showToast({ title: "视频大小不能超过500M", icon: "none" });
    return;
  }
  // 后续上传逻辑...
}
相关推荐
2501_915918414 小时前
HTTPS 代理失效,启用双向认证(mTLS)的 iOS 应用网络怎么抓包调试
android·网络·ios·小程序·https·uni-app·iphone
数字游民95275 小时前
半年时间大概上了70个web站和小程序,累计提示词超过20w
人工智能·ai·小程序·vibecoding·数字游民9527
说私域5 小时前
微商企业未来迭代的核心方向与多元探索——以链动2+1模式AI智能名片商城小程序为核心支撑
大数据·人工智能·小程序·流量运营·私域运营
27669582926 小时前
美团 小程序 mtgsig
python·小程序·node·js·mtgsig1.2·美团小程序·大众点评小程序
2501_915106326 小时前
混合应用(Hybrid)安全加固,不依赖源码对成品 IPA 混淆
android·安全·小程序·https·uni-app·iphone·webview
00后程序员张7 小时前
无需越狱,来对 iOS 设备进行调试、管理与分析
android·ios·小程序·https·uni-app·iphone·webview
芒果大胖砸7 小时前
uniapp当中如何实现长按复制功能并且能够自由选择内容
开发语言·javascript·uni-app
ujainu7 小时前
Flutter × OpenHarmony 实战:将闹钟、世界时钟、秒表、计时器四大模块集成至高保真鸿蒙时钟 App
flutter·华为·app·harmonyos
00后程序员张7 小时前
在 iOS 上架中如何批量方便快捷管理 Bundle ID
android·ios·小程序·https·uni-app·iphone·webview
韩立学长7 小时前
【开题答辩实录分享】以《智慧校园平台微信小程序》为例进行选题答辩实录分享
spring boot·微信小程序·小程序