html
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>OSS web直传</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js">
<script src="https://cdn.staticfile.org/codemirror/5.40.2/mode/javascript/javascript.min.js"></script>
</head>
<body>
<ul>
<li>
<span>上传至OSS的文件夹路径:</span>
<input type="text" name="dir" id="dir" value="test" placeholder="其填写上传目标文件夹名,OSS文件夹不存在时会自动生成,结尾不同加/">
</li>
<li>
<span>选择上传的文件:</span>
<input type="file" id="files"></li>
<li>
<button onclick="getOssSignature()">开始上传</button>
</li>
</ul>
</body>
<!--OSS服务端签名后直传JS逻辑代码-->
<script>
//发送ajax获取服务端签名
function getOssSignature(){
var file = $('#files').get(0).files[0];//获取需要上传的文件对象
//检测文件是否存在
if(!file){
alert('请先选择文件');
return false;
}
//检测是否没有输入OSS文件路径
if(!$('#dir').val()){
alert('请填写上传至OSS的文件夹路径');
return false;
}
var dir = $('#dir').val() + '/';
//获取上传的文件名,并得到文件后缀
var location=$("#files").val();
var point = location.lastIndexOf(".");
var file_type = location.substr(point);//获取文件后缀
var file_name = dir + (new Date()).getTime() + file_type;//将OSS文件路径与新的文件名拼接在一起,生成新的路径+文件名
//发送ajax请求我方php后端获取上传OSS时必要的参数信息
$.ajax({
type : "post", //提交方式
url : "http://127.0.0.1:82/WechatApi/getOssSignature",//路径
dataType:"json",
data : {
"dir" : dir
},//数据,这里使用的是Json格式进行传输
success : function(res) {//返回数据根据结果进行相应的处理
res = res.data;
//上返回的参数使用formData中
let formData = new FormData();
formData.append('key', file_name);
formData.append('OSSAccessKeyId', res.accessid);
formData.append('policy', res.policy);
formData.append('Signature', res.signature);
formData.append('callback', res.callback);
formData.append('success_action_status', 200); // 成功后返回的操作码
formData.append('file', file);
//接收到服务端返回的签名参数,开始通过另一个Ajax请求来上传文件到OSS
//成功获取签名后上传文件到阿里云OSS
$.ajax({
type : "POST", //提交方式
url : res.host,//路径
dataType:'json',
processData: false,
cache: false,
async: false,
contentType: false,
//关键是要设置contentType 为false,不然发出的请求头 没有boundary
//该参数是让jQuery去判断contentType
data : formData,//要发送到OSS数据,使用我这个ajax的格式可避开跨域问题。
success : function(res2) {//返回数据根据结果进行相应的处理
alert(res2.success);
//console.log(res2);//返回success:ok 说明你就上传成功了
}
});
}
});
}
</script>
</html>
PHP
<?php
/**
* @desc Oss
*
* @author Tao
* @email 804633234@qq.com
* @date 2022-09-15 11:45
* Class WechatApi
* @package app\ajax\controller
*/
class Oss
{
private $accessKeyId;
private $accessKeySecret;
private $host;
private $callbackUrl;
private $expire;
private $max_file;
public function __construct()
{
$this->accessKeyId="***";
$this->accessKeySecret="***";
$this->host="https://***.oss-cn-***.aliyuncs.com";
$this->callbackUrl="http://***/WechatApi/callBack";
$this->expire=30;
$this->max_file=1024*1024*500;
}
/**
* @desc 获取签名
*
* @param $dir 上传路径
* @author Tao
* @email 804633234@qq.com
* @date 2022-09-15 12:21
*/
public function getOssSignature($dir="")
{
$id = $this->accessKeyId;
$key = $this->accessKeySecret;
$host = $this->host;
//回调URL
$callbackUrl = $this->callbackUrl;
$dir = (string)$dir;
$callback_param = array('callbackUrl' => $callbackUrl,
'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}',
'callbackBodyType' => "application/x-www-form-urlencoded");
$callback_string = json_encode($callback_param);
$base64_callback_body = base64_encode($callback_string);
$now = time();
$expire = $this->expire;
$end = $now + $expire;
$expiration = $this->gmt_iso8601($end);
$condition = array(0 => 'content-length-range', 1 => 0, 2 => $this->max_file);
$conditions[] = $condition;
$start = array(0 => 'starts-with', 1 => '$key', 2 => $dir);
$conditions[] = $start;
$arr = array('expiration' => $expiration, 'conditions' => $conditions);
$policy = json_encode($arr);
$base64_policy = base64_encode($policy);
$string_to_sign = $base64_policy;
$signature = base64_encode(hash_hmac('sha1', $string_to_sign, $key, true));
$response = array();
$response['accessid'] = $id;
$response['host'] = $host;
$response['policy'] = $base64_policy;
$response['signature'] = $signature;
$response['expire'] = $end;
$response['callback'] = $base64_callback_body;
$response['dir'] = $dir;
return json_encode(['code' => 1, 'msg' => '获取成功','data'=>$response]);
}
/**
* @desc 时间编码
*
* @param $time
* @return string
* @throws \Exception
* @author Tao
* @email 804633234@qq.com
* @date 2022-09-15 13:53
*/
private function gmt_iso8601($time)
{
return (new \DateTime(null, new \DateTimeZone('UTC')))->setTimestamp($time)->format('Y-m-d\TH:i:s\Z');
}
/**
* @desc 回调
*
* @author Tao
* @email 804633234@qq.com
* @date 2022-09-15 15:49
*/
public function callBack(){
echo '{"success":"ok"}';
}
}
?>