如何将图片视频上传至阿里云OSS服务器实例
临时地址上传
####
前端代码
####
<uni-section title="图片" type="line">
<view style="padding: 0 20rpx;">
<uni-file-picker v-model="imageFile" mode="list" ref="image" limit="1" file-mediatype="image" :auto-upload="false" @select="selectImage">
<button class="mini-btn" type="primary" size="mini">选择图片</button>
</uni-file-picker>
</view>
</uni-section>
<uni-section title="视频" type="line">
<view style="padding: 0 20rpx;">
<uni-file-picker v-model="videoFile" ref="video" limit="1" file-mediatype="video" :auto-upload="false" @select="selectVideo">
<button class="mini-btn" type="primary" size="mini">选择视频</button>
</uni-file-picker>
</view>
</uni-section>
<script setup>
const image= ref()
const imageObject = reactive({
extname: "",
size: "",
fileType: ""
})
const imageFile = ref()
const imageSrc = ref()
const video = ref()
const videoObject = reactive({
extname: "",
size: "",
fileType: ""
})
const videoFile = ref()
const videoSrc = ref()
const selectImage = (e) => {
image.value = e.tempFilePaths[0]
imageObject.extname = e.tempFiles[0].extname
imageObject.size = e.tempFiles[0].size
imageObject.fileType = e.tempFiles[0].fileType
}
const selectVideo = (e) => {
video.value = e.tempFilePaths[0]
videoObject.extname = e.tempFiles[0].extname
videoObject.size = e.tempFiles[0].size
videoObject.fileType = e.tempFiles[0].fileType
}
const uploadImageToOss = async () => {
if(!image.value){
uni.showToast({
title: "请选择图片",
icon: "none"
})
return false
}
let res = await apiGetSignUrl({extname: imageObject.extname, size: imageObject.size, fileType: imageObject.fileType})
if(res.errcode != 9){
uni.showToast({
title: res.msg,
icon: "none"
})
return false;
}
try {
// 读取文件为 ArrayBuffer
const buffer = await getArrayBufferFromFile(image.value);
// 发起 PUT 请求上传文件
const result = await uni.request({
url: res.data.signUrl,
method: 'PUT',
header: {
'Content-Type': res.data.contentType
},
dataType: 'arraybuffer', // 必须指定为 arraybuffer
data: buffer
});
imageSrc.value = res.data.url;
return true;
} catch (e) {
uni.showToast({
title: e,
icon: "none"
})
return false;
}
}
const uploadVideoToOss = async () => {
if(!video.value){
uni.showToast({
title: "请选择视频",
icon: "none"
})
return false
}
uni.showLoading({
title: '上传视频中...',
mask: true
})
try{
let res = await apiGetSignUrl({extname: videoObject.extname, size: videoObject.size, fileType: videoObject.fileType})
if(res.errcode == 9){
// 读取文件为 ArrayBuffer
const buffer = await getArrayBufferFromFile(video.value);
// 发起 PUT 请求上传文件
const result = await uni.request({
url: res.data.signUrl,
method: 'PUT',
header: {
'Content-Type': res.data.contentType
},
dataType: 'arraybuffer', // 必须指定为 arraybuffer
data: buffer
});
videoSrc.value = res.data.url;
return true;
}else{
uni.showToast({
title: res.msg,
icon: "none"
})
return false;
}
}catch(e){
uni.showToast({
title: e,
icon: "none"
})
return false;
}finally{
uni.hideLoading()
}
}
</script>
// 获取文件的 ArrayBuffer
export function getArrayBufferFromFile(filePath) {
return new Promise((resolve, reject) => {
// #ifdef APP-VUE || MP-WEIXIN || MP-ALIPAY
// 小程序 / App 使用 uni.getFileSystemManager()
try {
const fs = uni.getFileSystemManager();
fs.readFile({
filePath: filePath,
success: res => {
resolve(res.data); // ArrayBuffer
},
fail: err => {
reject(err);
}
});
} catch (e) {
reject(e);
}
// #endif
// #ifdef H5
// H5 平台使用 fetch + blob + arrayBuffer
fetch(filePath)
.then(response => {
if (!response.ok) throw new Error("HTTP 请求失败");
return response.arrayBuffer();
})
.then(buffer => {
resolve(buffer);
})
.catch(err => {
reject(err);
});
// #endif
});
}
###
后端代码
###
function getsignurl_action()
{
$extname = isset($_POST['extname']) ? strtolower(strval($_POST['extname'])) : '';
$size = isset($_POST['size']) ? intval($_POST['size']) : 0;
$fileType = isset($_POST['fileType']) ? strtolower(strval($_POST['fileType'])) : '';
$duration = isset($_POST['duration']) ? intval($_POST['duration']) : 0;
$uid = $this->uid;
$usertype = $this->usertype;
if(!$uid){
return jsonErr('请先登录');
}
if(empty($usertype)){
return jsonErr('请先选择身份');
}
if($fileType === 'image'){
$allowedTypes = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array($extname, $allowedTypes)) {
return jsonErr("不允许的文件类型. 允许的类型为: " . implode(", ", $allowedTypes));
}
$maxSize = 2000000;
if ($size > $maxSize) {
return jsonErr("文件过大. 最大允许大小为: " . ($maxSize / 1000000) . "MB");
}
} elseif ($fileType === 'video'){
$allowedTypes = ['mp4', 'avi', 'mov', 'mkv', 'flv', 'webm'];
if (!in_array($extname, $allowedTypes)) {
return jsonErr("不允许的文件类型. 允许的类型为: " . implode(", ", $allowedTypes));
}
if($duration > 60){
return jsonErr("视频时长过长,建议60秒以内");
}
} else{
return jsonErr('格式错误');
}
$ossModel = $this->MODEL('alioss');
$res = $ossModel->getUploadFileSignUrl($uid, $extname);
if($res['code'] === true){
return jsonSuc($res['msg']);
}else{
return jsonErr($res['msg']);
}
}
临时签名上传
###
前端代码
###
<script src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.20.0.min.js"></script>
<div class="drawerModLis">
<div class="drawerModTite">
<span>视频封面</span>
</div>
<div class="drawerModInpt">
<el-upload
class="upload-demo"
action=""
:on-change="handleImageChange"
:file-list="imageList"
:auto-upload="false">
<el-button slot="trigger" size="small" type="primary">选取图片</el-button>
</el-upload>
</div>
<div class="drawerModTips">
<div v-if="info.image">
<el-link type="primary" :href="info.image" target="_blank">查看封面</el-link>
</div>
</div>
</div>
<div class="drawerModLis">
<div class="drawerModTite">
<span>视频文件</span>
</div>
<div class="drawerModInpt">
<el-upload
class="upload-demo"
action=""
:on-change="handleVideoChange"
:file-list="videoList"
:auto-upload="false">
<el-button slot="trigger" size="small" type="primary">选取视频</el-button>
</el-upload>
</div>
<div class="drawerModTips">
<div v-if="info.video">
<el-link type="primary" :href="info.video" target="_blank">查看视频</el-link>
</div>
</div>
</div>
async saveOss(){
let _this = this;
const formData = new FormData();
let params = _this.info;
let baseUrl = localStorage.getItem("baseUrl") + '?';
Object.keys(params).forEach((key) => {
formData.append(key, params[key]);
});
if (_this.imageList.length > 0 || _this.videoList.length > 0) {
const response = await fetch(baseUrl + 'c=shipin&a=getsts', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({uid: _this.info.uid, usertype: _this.info.usertype})
});
if (!response.ok) {
message.error("获取临时凭证失败");
return false;
}
const res = await response.json();
if (res.error == 0) {
const client = new OSS({
bucket: res.data.Bucket,
region: res.data.Region,
accessKeyId: res.data.AccessKeyId,
accessKeySecret: res.data.AccessKeySecret,
stsToken: res.data.SecurityToken,
});
if(_this.imageList.length > 0){
const uid = _this.info.uid;
const time = _this.getNowTime();
const ext = _this.getFileExt(_this.imageList[0].name);
const object = `${uid}/${time}.${ext}`;
try {
await client.put(object, _this.imageList[0].raw);
formData.append('imageFile', res.data.Host + '/' + object);
} catch (e) {
message.error(e);
return false;
}
}
if(_this.videoList.length > 0){
startLoading()
const uid = _this.info.uid;
const time = _this.getNowTime();
const ext = _this.getFileExt(_this.videoList[0].name);
const object = `${uid}/${time}.${ext}`;
try {
await client.put(object, _this.videoList[0].raw);
formData.append('videoFile', res.data.Host + '/' + object);
endLoading()
} catch (e) {
message.error(e);
return false;
}
}
} else {
message.error(res.msg);
return false;
}
}
httpPost('c=shipin&a=add', formData).then(function (result) {
var res = result.data
if (res.error == 0) {
message.success(res.msg, function () {
_this.getList();
_this.draweradd = false;
_this.imageList = [];
_this.videoList = [];
})
} else {
message.error(res.msg);
}
}).catch(function (e) {
console.log(e)
})
},
###
后端代码
###
public function getsts_action()
{
// 获取原始的 POST 数据(适用于 application/json)
$data = json_decode(file_get_contents('php://input'), true);
$uid = isset($data['uid']) ? intval($data['uid']) : 0;
$usertype = isset($data['usertype']) ? intval($data['usertype']) : 0;
$ossModel = $this->MODEL('alioss');
$res = $ossModel->getSTS();
if($res['code'] === true){
$this->render_json(0, '', $res['msg']);
}else{
$this->render_json(1, $res['msg']);
}
}
阿里云代码
<?php
//ini_set('display_errors', 1);
//ini_set('display_startup_errors', 1);
//error_reporting(E_ALL);
require_once __DIR__ . '/aliyunsdk/vendor/autoload.php';
use OSS\Credentials\StaticCredentialsProvider;
use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Http\RequestCore;
use OSS\Http\ResponseCore;
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use AlibabaCloud\Sts\Sts;
class alioss
{
protected $accessKeyId;
protected $accessKeySecret;
protected $provider;
protected $endpoint;
protected $bucket;
protected $config;
protected $ossClient;
protected $options;
protected $host;
protected $region;
protected $ramArn;
public function __construct()
{
$this->accessKeyId = "";
$this->accessKeySecret = "";
$this->provider = new StaticCredentialsProvider($this->accessKeyId, $this->accessKeySecret);
$this->endpoint = "";
$this->bucket = "";
$this->host = "";
$this->region = "";
$this->ramArn = "";
$this->config = array(
"provider" => $this->provider,
"endpoint" => $this->endpoint,
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V4,
"region"=> $this->region
);
$this->options = array(
OssClient::OSS_HEADERS => array(
OssClient::OSS_ACL => "public-read"
)
);
$this->ossClient = new OssClient($this->config);
}
public function uploadFile($object, $filePath){
try {
$this->ossClient->uploadFile($this->bucket, $object, $filePath, $this->options);
return array(
'code' => true,
'msg' => $this->host . '/' . $object
);
} catch (OssException $e) {
return array(
'code' => false,
'msg' => $e->getMessage()
);
}
}
public function multiuploadFile($object, $filePath){
try {
$options = array(
OssClient::OSS_CHECK_MD5 => true,
OssClient::OSS_PART_SIZE => 5,
OssClient::OSS_HEADERS => array(
OssClient::OSS_ACL => "public-read"
)
);
$this->ossClient->multiuploadFile($this->bucket, $object, $filePath, $options);
return array(
'code' => true,
'msg' => $this->host . '/' . $object
);
} catch (OssException $e) {
return array(
'code' => false,
'msg' => $e->getMessage()
);
}
}
public function deleteFile($object){
try {
$this->ossClient->deleteObject($this->bucket, $object);
return array(
'code' => true,
'msg' => ''
);
} catch (OssException $e) {
return array(
'code' => false,
'msg' => $e->getMessage()
);
}
}
public function getUploadFileSignUrl($uid, $extname)
{
$contentType = $this->getMimeType($extname);
$time = time();
$object = "${uid}/${time}.${extname}";
try {
$ossClient = new OssClient($this->accessKeyId, $this->accessKeySecret, $this->endpoint, false);
// 生成签名URL。
$signedUrl = $ossClient->signUrl($this->bucket, $object, $timeout = 3600, "PUT", array('Content-Type' => $contentType));
return array(
'code' => true,
'msg' => array(
'contentType' => $contentType,
'url' => $this->host . '/' . $object,
'signUrl' => $signedUrl
)
);
} catch (OssException $e) {
return array(
'code' => false,
'msg' => $e->getMessage()
);
}
}
public function getMimeType($ext)
{
$types = [
// 图片
'png' => 'image/png',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'gif' => 'image/gif',
'webp' => 'image/webp',
'svg' => 'image/svg+xml',
// 视频
'mp4' => 'video/mp4',
'avi' => 'video/x-msvideo',
'mov' => 'video/quicktime',
'webm' => 'video/webm',
'mkv' => 'video/x-matroska',
'flv' => 'video/x-flv',
];
return $types[$ext];
}
public function getSTS()
{
// 初始化阿里云客户端。
AlibabaCloud::accessKeyClient($this->accessKeyId, $this->accessKeySecret)
->regionId($this->region)
->asDefaultClient();
try {
// 创建STS请求。
$result = Sts::v20150401()
->assumeRole()
// 设置角色ARN。
->withRoleArn($this->ramArn)
// 指定自定义角色会话名称,用来区分不同的令牌。
->withRoleSessionName('userUpload')
// 指定STS临时访问凭证过期时间为3600秒。
->withDurationSeconds(900)
->request();
// 获取响应中的凭证信息。
$credentials = $result['Credentials'];
return array(
'code' => true,
'msg' => array(
'AccessKeyId' => $credentials['AccessKeyId'],
'AccessKeySecret' => $credentials['AccessKeySecret'],
'SecurityToken' => $credentials['SecurityToken'],
'Expiration' => $credentials['Expiration'],
'Bucket' => $this->bucket,
'Region' => 'oss-' . $this->region,
'Host' => $this->host
)
);
} catch (ClientException $e) {
return array(
'code' => false,
'msg' => $e->getErrorMessage()
);
} catch (ServerException $e) {
return array(
'code' => false,
'msg' => $e->getErrorMessage()
);
}
}
public function handleUrl($endpoint, $bucket, $object){
if(filter_var($endpoint, FILTER_VALIDATE_URL)){
$arr = parse_url($endpoint);
$scheme = $arr['scheme'];
$host = $arr['host'];
$url = $scheme . '://' . $bucket . '.' . $host . '/' . $object;
return $url;
}
}
public function handlePath($url){
$parsedUrl = parse_url($url);
$path = isset($parsedUrl['path']) ? $parsedUrl['path'] : '';
if ($path !== '' && $path[0] === '/') {
// 如果路径以斜杠开始,则移除它
$trimmedPath = substr($path, 1);
} else {
// 否则保持原样
$trimmedPath = $path;
}
return $trimmedPath;
}
}