七牛云是国内算是挺不错的图片存储服务器,免费用户能拥有10G空间,每个月10G的下载流量,对于个人用户用于做个小博客,小网站来说,已经够了。
但是,七牛的官方开发文档真心会看得一头雾水。
于是,先记录下来这次传图的过程。
在上传图片之前,需要准备两样东西:
- AccessKey
- SecretKey
其中, AccessKey 和 SecretKey 能在 个人中心 > 秘钥管理中获得,如图。
- 创建空间 并 创建配置文件
- 选择 资源主页 ,再选择 立即添加,或者选择 对象存储 ,然后选择 添加 。
- 然后填上空间的名字,选择区域即可。
- 其中,空间的名字是我们使用代码上传至七牛服务器的第三个参数 Bucket
- 可以将这3个常量存储在配置文件config.qiniu.php中
define('QINIU_SECRET_KEY', 'YOUR_SK');
define('QINIU_ACCESS_KEY', 'YOUR_AK');
define('QINIU_DOMAIN', 'YOUR_QINIU_DOMAIN');
define('QINIU_BUCKET', 'YOUR_BUCKET_NAME');
- 获取上传凭证
- 上传凭证的作用:
客户端上传前需要先从服务端获取上传凭证,并在上传资源时将上传凭证作为请求内容的一部分。不带凭证或带非法凭证的请求将返回 HTTP 错误码 401,代表认证失败。
生成规则:
1.构造上传策略:
上传策略是资源上传时附带的一组配置设定。通过这组配置信息,七牛云存储可以了解用户上传的需求:它将上传什么资源,上传到哪个空间,上传结果是回调通知还是使用重定向跳转,是否需要设置反馈信息的内容,以及授权上传的截止时间等等。
{
"scope": "<Bucket string>",
"deadline": <UnixTimestamp uint32>,
"insertOnly": <AllowFileUpdating int>,
"endUser": "<EndUserId string>",
"returnUrl": "<RedirectURL string>",
"returnBody": "<ResponseBodyForAppClient string>",
"callbackUrl": "<RequestUrlForAppServer string>",
"callbackHost": "<RequestHostForAppServer string>",
"callbackBody": "<RequestBodyForAppServer string>",
"callbackBodyType": "<RequestBodyTypeForAppServer string>",
"callbackFetchKey": <RequestKeyForApp int>
"persistentOps": "<persistentOpsCmds string>",
"persistentNotifyUrl": "<persistentNotifyUrl string>",
"persistentPipeline": "<persistentPipeline string>",
"saveKey": "<SaveKey string>",
"fsizeMin": <FileSizeMin int64>,
"fsizeLimit": <FileSizeLimit int64>,
"detectMime": <AutoDetectMimeType int>,
"mimeLimit": "<MimeLimit string>"
"deleteAfterDays": "<deleteAfterDays int>"
}
- 如现有如下上传策略:
$putPolicy = array(
'scope' => QINIU_BUCKET.':'.$filename ,
'deadline' => time()+3600 ,
'returnBody' => '{
"name": $(fname),
"file_url": $(x:file_url)
}'
);
- 该上传策略定义了:
1. 指定了图片上传至`QINIU_BUCKET`存储空间中,同时,该token只允许文件名为 `$filename` 的文件上传。 2. token有效时间为1个小时。 3. 设置返回信息,返回上传的文件的文件名,和自定义参数中的 `file_url`
- 将上传策略序列化成为JSON格式:
- 用户可以使用各种语言的 JSON 库,也可以手工拼接字符串。序列化后,应得到如下形式的字符串(字符串值以外部分不含空格或换行):
$putPolicy = json_encode($putPolicy);
- 或
$putPolicy = '{
"scope": "my-bucket:sunflower.jpg",
"deadline":1451491200,
"returnBody":
"{
\"name\":$(fname),
\"size\":$(fsize),
\"w\":$(imageInfo.width),
\"h\":$(imageInfo.height),
\"hash\":$(etag)
}"
}'
- 对 JSON 编码的上传策略进行URL安全的Base64编码,得到待签名字符串:
- 官方给的demo代码为:
encodedPutPolicy = urlsafe_base64_encode(putPolicy)
- 运行之后,发现 urlsafe_base64_encode 这个函数是自定义的,估计相当于将 +,/号转换为 -,_
function _urlsafe_base64_encode($str){
$find = array('+', '/');
$replace = array('-', '_');
return str_replace($find, $replace, base64_encode($str));
}
- 使用SecretKey对上一步生成的待签名字符串计算HMAC-SHA1签名:
- 官方给的demo代码为:
sign = hmac_sha1(encodedPutPolicy, QINIU_SECRET_KEY)
- 然而, hmac_sha1 这个函数也不是php自带的。经过搜索发现,其实PHP5.1.2之后的版本内置了直接产生的函数,只是名字不一样罢了: hash_hmac,因此需要将这里修改为:
$sign = hash_hmac('sha1' ,$encodedPutPolicy, QINIU_SECRET_KEY, true);
- 第一个参数为哈希算法名(支持md5,sha256,haval160,4等,具体可到 hash_algos()中查询);第二个参数为需要进行哈希的信息;第三个参数为秘钥;第四个参数为输出格式(true为输出二进制,false为输出16进制)
- 对签名进行URL安全的Base64编码:
- 官方代码:
encodedSign = urlsafe_base64_encode(sign)
- 这里的 urlsafe_base64_encode 依然为上述的自定义函数。
- 将AccessKey、encodedSign 和 encodedPutPolicy 用英文符号 : 连接起来:
$uploadToken = QINIU_ACCESS_KEY . ':' . $encodedSign . ':' . $encodedPutPolicy
- 返回token至客户端
echo json_encode(array('token' => $uploadToken, 'key' => $filename, 'fileurl' => QINIU_DOMAIN));
- 这里返回了文件名和文件url,主要是因为,保证文件在七牛中的唯一性,和可以随时更改七牛的空间访问地址。
- 上传图片
- 使用js直接上传图片至七牛服务器他的过程为:
- 向服务器请求 uploadToken =>
- 获取 ‘uploadToken` 后上传图片 =>
- 上传成功,显示图片。
- 这里没有使用 zepto jquery 这种库,所以浏览器的兼容性为兼容 FormData 的现代浏览器
- 使用 xhr 和 FormData 进行异步传输数据。
function ajax(options){
options.start && options.start.call('start');
//执行上传操作
var xhr = new XMLHttpRequest();
xhr.open("post", options.url, true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
returnDate = JSON.parse(xhr.responseText);
options.success && options.success.call('success', returnDate);
};
};
//表单数据
var fd = new FormData();
for (k in options.data) {
fd.append(k, options.data[k]);
}
fd.append('file', options.file);
//执行发送
result = xhr.send(fd);
}
新建一个表单 form
<form action="" method="post" name="upload_form" hidden> <input type="file" name="file"> <input type="hidden" name="key" value=""> <input type="hidden" name="x:file_url" value=""> <input type="hidden" name="token" value=""> </form>
- 给上传文件的按钮绑定一个 change 时间:
file.addEventListener('change', function(e){
var selected_file = e.target.files[0];
// 先请求服务器获取token
ajax({
url: '/upload.php',
data: {
filename: selected_file.name
},
start: function(){
console.log('start to get uploadToken');
},
success: function(data){
// 给表单中的参数赋值
form.key.value = data.key;
form.file_url.value = data.fileurl+data.key;
form.token.value = data.token;
// 执行上传图片操作
uploadImage(selected_file)
}
})
})
开始上传文件至七牛
function uploadImage(file){
ajax({
// 如果
url: 'http://upload.qiniu.com/',
// url: 'https://up.qbox.me',
data: {
file: file,
key: form.key.value,
'x:file_url': form.file_url.value,
token: form.token.value,
},
start: function(){
console.log('start to upload Image to Qiniu');
},
success: function(data){
// 给表单中的参数赋值
console.log(data);
image.src = data.file_url
}
})
}
最终实现
希望本文能帮助到您!
点赞+转发,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓-_-)
关注 {我},享受文章首发体验!
每周重点攻克一个前端技术难点。更多精彩前端内容私信 我 回复“教程”

本文暂时没有评论,来添加一个吧(●'◡'●)