oss(阿里云)前端直传

  • WEB端前端直传

参考文档:web前端直传并设置上传回调

封装oss-upload.ts

// 图片上传
import { uploadToken } from '@/api/uploadFile.js' // 获取oss token接口// 定义 OSS 信息类型
interface OssInfo {policy: string;signature: string;x_oss_credential: string;x_oss_date: string;dir: string;security_token: string;callback: string;host: string;data?: {filename?: string;url?: string;};
}// 定义 uploadToken 返回数据类型
interface UploadTokenResponse {status_code: number;data: OssInfo;
}let ossInfo: OssInfo | null = null// 定义文件类型
type FileWithMetadata = File & {base64?: string;width?: number;height?: number;url?: string;fileType?: string;raw?: File;thumbdata?: string;
};/*** 文件上传数组* 过滤已上传文件* @param {FileWithMetadata[]} files 要上传的文件数组* @returns {Promise<{ sucArr: FileWithMetadata[]; failArr: FileWithMetadata[] }>} 包含上传成功和失败文件的Promise*/
export async function fileUpload(files: FileWithMetadata[]): Promise<{ sucArr: FileWithMetadata[]; failArr: FileWithMetadata[] }> {const sucArr: FileWithMetadata[] = []const failArr: FileWithMetadata[] = []return new Promise((resolve) => {const result = files.reduce((accumulatorPromise: Promise<void>, next: FileWithMetadata) => {return accumulatorPromise.then(() => { // 上一个接口执行完毕再执行下一个if (!next.url || !next.url.includes(import.meta.env.VITE_APP_UPLOAD_API)) {return uploadItemHandle((next.fileType === 'file' && next.raw) ? next.raw : next).then((res) => {sucArr.push(res)}).catch((res) => {failArr.push(res)})} else {sucArr.push(next)}})}, Promise.resolve())result.then(() => {console.log('All Promises Resolved', { sucArr, failArr })resolve({ sucArr, failArr })})})
}/*** 文件处理* @param {FileWithMetadata} file 要上传的文件* @returns {Promise<FileWithMetadata>} 包含上传成功文件的Promise*/
function uploadItemHandle(file: FileWithMetadata): Promise<FileWithMetadata> {return new Promise(async(resolve, reject) => {if (!ossInfo) { // 减少调用接口次数const data = await uploadToken() as UploadTokenResponseif (Number(data.status_code) === 200) {ossInfo = data.data}}if (!ossInfo) return reject(file)const formData = new FormData()formData.append('success_action_status', '200')formData.append('policy', ossInfo.policy)formData.append('x-oss-signature', ossInfo.signature)formData.append('x-oss-signature-version', 'OSS4-HMAC-SHA256')formData.append('x-oss-credential', ossInfo.x_oss_credential)formData.append('x-oss-date', ossInfo.x_oss_date)formData.append('key', ossInfo.dir + file.name) // 文件名formData.append('x-oss-security-token', ossInfo.security_token)formData.append('callback', ossInfo.callback) // 添加回调参数formData.append('file', file) // file 必须为最后一个表单域try {const response = await fetch(ossInfo.host, { method: 'POST', body: formData })if (!response.ok) throw new Error(`请求失败: ${response.status}`)const imgData = await response.json()if (imgData.status === 200 && imgData.data) {file.thumbdata = imgData.data.filename || ''file.url = imgData.data.url || ''resolve(file)} else {console.error(JSON.stringify(imgData))reject(file)}} catch (error) {console.error(error)reject(file)}})
}

调用:

await fileUpload(list).then(arr => {if (arr.failArr.length === 0) {console.log('上传数据返回:',arr)} else {ElMessage({ message: `有文件上传失败请重新上传!`, type: 'error', duration: 2 * 1000 })}
}).catch(() => {return { sucArr: [] }
})

微信小程序端
参考文档:微信小程序端前端直传
ossUpload.js

(function () {const {request} = require('./request')let ossInfo = nullfunction uploadFile(filePath, success, fail, options, progress, cancelTask) {let successResult = []let failResult = []const result = filePath.reduce((accumulatorPromise, next) => {return accumulatorPromise.then(() => { // 上一个接口执行完毕再执行下一个return uploadItem(next).then((res => {successResult = successResult.concat(res)})).catch(res => {failResult = failResult.concat(res)})})}, Promise.resolve())result.then(e => {if (failResult.length === 0) success(successResult)else fail(successResult)})}// 正式上传的前置方法,做预处理function uploadItem(file) {return new Promise(async (resolve, reject) => {if (!ossInfo) {const data = await getOssToken()if (Number(data.status_code) === 200) {ossInfo = data.dataossInfo = data}}console.log('file',file)if (!ossInfo) return reject(file)// 上传参数const formData = {key:file.tempFilePath.split('/').pop(), //上传文件名称policy: ossInfo.policy, //表单域'x-oss-signature-version': ossInfo.xOssSignatureVersion, //指定签名的版本和算法'x-oss-credential': ossInfo.xOssCredential, //指明派生密钥的参数集'x-oss-date': ossInfo.xOssDate, //请求的时间'x-oss-signature': ossInfo.xOssSignature, //签名认证描述信息'x-oss-security-token': ossInfo.xOssSecurityToken, //安全令牌success_action_status: ossInfo.success_action_status //上传成功后响应状态码};// 发送请求上传文件 wx.uploadFile({// Bucket域名 请替换为目标Bucket域名url: ossInfo.base_url, // 此域名仅作示例,实际Bucket域名,请替换为您的目标Bucket域名。filePath: file.tempFilePath,name: 'file', //固定值为fileformData: formData,success(res) {console.log('上传响应:', res);if (res.statusCode === 200) {resolve(res.data); // 上传成功} else {console.error('上传失败响应:', res);reject(res); // 上传失败,返回响应}},fail(err) {console.error('上传失败:', err); // 输出错误信息reject(err); // 调用回调处理错误}});})}// 获取阿里云tokenfunction getOssToken() {return new Promise((resolve, reject) => {const data = {url: 'api/sts-token', // 获取oss token接口method: 'post'}request(data, true, false, '操作中...', 2000).then((res) => {resolve(res)}).catch((err) => {reject('token获取失败' + err)})})}module.exports = {uploadFile}
})();

使用:
index.js

const {uploadFile} = require('../../utils/ossUpload')Component({data: {image: [],},pageLifetimes: {show() {if (typeof this.getTabBar === 'function') {this.getTabBar((tabBar) => {tabBar.setData({selected: 0})})}}},methods: {onUpload() {uploadFile(this.data.image, (res) => {console.log('成功', res)this.onSubmit()}, (err) => {console.log('失败', err)})},onSubmit() {console.log('好啦')},uploadImg() {wx.chooseMedia({count: 9,mediaType: ['image', 'video'],sourceType: ['album', 'camera'],maxDuration: 30,camera: 'back',success: (res) => {console.log(res.tempFiles)this.setData({image: res.tempFiles})}})}}
})

index.wxml:

<button bind:tap="uploadImg">上传</button>
<image wx:for="{{image}}" src="{{item.tempFilePath}}" mode="" />
<button bind:tap="onUpload">提交</button>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/93003.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/93003.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vscode uv 发布一个python包:编辑、调试与相对路径导包

背景 最近一直在使用uv做python包管理&#xff0c;用起来很方便。 尤其是在代码上传到github的时候&#xff0c;pyproject.toml 会显示出当前项目依赖的python包。这样在把代码下载到本地之后&#xff0c;直接uv sync就可以很方便地恢复出python环境。 uv 除了有上述优点&…

Secure 第四天作业

实验需求&#xff1a;需求一拓扑&#xff1a;按照以上拓扑所示&#xff0c;完成以下需求&#xff1a;参考以上拓扑&#xff0c;配置设备IP地址&#xff0c;使用UNL里Secure第四天拓扑即可。&#xff08;有兴趣的同学课后也可按照PPT原拓扑做做实验&#xff09;&#xff1b;配置…

利用开漏输出模式模拟IIC

/************************************************************利用IO口模拟IIC时序&#xff0c;需要使用2个IO口(SDA和SCL)SCL时钟线只能由主器件进行控制&#xff0c;所以SCL引脚必须为输出模式SDA数据线&#xff0c;在主器件发送数据时&#xff0c;SDA引脚为输出模式SDA数…

闸机控制系统从设计到实现全解析:第 5 篇:RabbitMQ 消息队列与闸机通信设计

第 5 篇&#xff1a;RabbitMQ 消息队列与闸机通信设计RabbitMQ 是一款开源的消息队列中间件&#xff08;Message Queue&#xff0c;MQ&#xff09;&#xff0c;基于 Erlang 语言开发&#xff0c;遵循 AMQP&#xff08;Advanced Message Queuing Protocol&#xff0c;高级消息队…

Linux 常用命令大全:覆盖日常 99% 操作需求

1、基本命令 pwd&#xff1a;显示当前工作目录的绝对路径&#xff0c;例如在复杂目录结构中快速确认位置&#xff0c;执行后会输出类似/home/user/documents的结果。 cd&#xff1a;切换目录&#xff0c;cd 目录路径可进入指定目录&#xff0c;cd ~回到当前用户的家目录&…

普通电脑与云电脑的区别有哪些?全面科普

近年来&#xff0c;越来越多的人不再购置升级自己的电脑&#xff0c;转而选择云电脑&#xff0c;云端产品正在变得越来越普及易用。那么它究竟跟我们的普通本地设备有什么区别呐&#xff1f;或许很多人并不知悉&#xff0c;对此&#xff0c;本篇内容小编就为大家简要科普一下普…

【Python】支持向量机SVM

示例代码&#xff1a;import numpy as np import matplotlib.pyplot as plt from sklearn import svm from sklearn.datasets import make_blobs from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, classification_report# 设…

当AI学会“抄近路”:残差网络如何突破深度学习的极限

**——解读《Deep Residual Learning for Image Recognition》**今天我想带大家回到2015年&#xff0c;见证人工智能领域的一场“捷径革命”——由何恺明等人提出的**深度残差学习框架&#xff08;ResNet&#xff09;**。这篇论文解决了困扰AI界多年的“深度诅咒”&#xff0c;…

HCIP--BGP综合实验

目录 BGP综合实验报告 一、实验拓扑 二、实验要求 三、实验思路 &#xff08;一&#xff09;IP地址规划 &#xff08;二&#xff09;整体思路 四、实验步骤 &#xff08;一&#xff09; IP地址配置 &#xff08;二&#xff09; AS2内部配置OSPF协议 &#xff08;三&a…

Java 基础编程案例:从输入交互到逻辑处理

在Java编程学习中&#xff0c;输入输出、循环控制和逻辑判断是核心基础。本文整理了10个经典案例&#xff0c;涵盖Scanner输入处理、斐波那契数列、成绩统计、登录验证等场景&#xff0c;帮助初学者掌握编程逻辑与实用技巧。 一、Scanner输入交互&#xff1a;获取用户输入并处理…

LeetCode 面试经典 150_数组/字符串_整数转罗马数字(18_12_C++_中等)(模拟)(对各位进行拆解)

LeetCode 面试经典 150_数组/字符串_整数转罗马数字&#xff08;18_12_C_中等&#xff09;题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;思路一&#xff08;模拟&#xff09;&#xff1a;思路二&#xff08;对各位进行拆解&#xff09;&a…

计算机网络摘星题库800题笔记 第6章 应用层

第6章 应用层 6.1 网络应用的架构 考点 1 CS 架构 题组闯关 1.DNS 是基于 ( ) 模式的分布式系统。 A. C/S B. B/S C. P2P D. 以上均不正确 1.【参考答案】A 【解析】本题考查网络应用模型。 DNS 作为分布式应用&#xff0c;是一种典型的 C/S 模式&#xff0c;是随着 Internet 技…

BLUCK电路的输入电容应该怎么选取

借用TI的BULK芯片讨论一下输入电容怎么选取的问题&#xff0c;BULK电源是我们常用的电源&#xff0c;它的原理请看之前的文章&#xff1a; 高压差为何不用LDO&#xff1f;DCDC效率更高&#xff01;-CSDN博客 本文我们探讨一下输入电容&#xff0c;输入电容是控制纹波的关键&a…

CAN仲裁机制的原理

我们来详细讲 CAN 仲裁机制 的原理和工作方式,这是 CAN 总线最核心的特性之一。 1️⃣ 基本概念 CAN 总线是 多主机、多节点的串行总线,所有节点共享一根差分信号线(CAN_H / CAN_L)。 每个节点都可以随时发送消息(多主机机制) 总线只能同时有一个节点成功发送 仲裁 用…

【GPT入门】第46课 vllm安装、部署与使用

【GPT入门】第46课 vllm安装、部署与使用 1.准备服务器 2. 安装 conda环境,隔离base环境 3. vllm使用 3.1 在线推理, openai兼容服务器 3.2 模型离线调用 4. 没有使用GPU问题分析 1.准备服务器 cuda 版本选12.1 vllm官网介绍: https://vllm.hyper.ai/docs/getting-started/…

【从网络基础到实战】理解TCP/IP协议体系的核心要点(包含ARP协议等其他协议介绍)

前言&#xff1a; 学习计算机网络不仅是软件开发的基础功&#xff0c;更是成为一名合格后端工程师、网络工程师的重要门槛。本文将基于 TCP/IP 协议体系&#xff0c;系统梳理网络层、数据链路层、以及相关协议的核心知识&#xff0c;并结合实际案例与代码示例帮助理解。一、网络…

Python 元类基础:从理解到应用的深度解析

在 Python 的高级编程中&#xff0c;元类&#xff08;metaclass&#xff09; 无疑是最神秘又最强大的特性之一。它不仅是构建类的“工厂”&#xff0c;更是 Python 灵活对象模型的体现。本文将带你从基础概念入手&#xff0c;深入理解元类的本质、工作机制以及实际应用&#xf…

Nginx 配置代理服务器的详细方法

一、什么是代理服务器&#xff1f; 类型说明正向代理客户端通过代理访问目标服务器&#xff08;隐藏客户端身份&#xff09;反向代理客户端访问代理服务器&#xff0c;由代理服务器请求后端服务器&#xff08;隐藏后端服务器&#xff09; 二、Nginx 反向代理配置方法&#xff…

Lombok插件介绍及安装(Eclipse)

一、Lombok 的用途 Lombok是一个 Java 库&#xff0c;通过注解的方式简化 Java 代码的编写。它能够自动生成常见的代码&#xff0c;如getter、setter、toString、equals、hashCode等方法&#xff0c;从而减少样板代码&#xff0c;使代码更加简洁、易读。 Lombok 通过添加**Dat…

硬核操作!Go 语言生成 “会爬墙的清洁机器人”,玻璃外墙自己擦

本文聚焦于利用 Go 语言开发 “会爬墙的清洁机器人” 这一硬核技术&#xff0c;围绕该机器人如何实现玻璃外墙自主清洁展开。首先介绍开发背景与需求&#xff0c;接着阐述 Go 语言在其中的优势&#xff0c;详细讲解机器人的核心技术&#xff0c;包括吸附系统、运动控制、清洁机…