编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

使用七牛云存储图片 之 上传图片(上传图片到七牛云并返回图片url)

wxchong 2024-07-15 09:53:57 开源技术 13 ℃ 0 评论

七牛云是国内算是挺不错的图片存储服务器,免费用户能拥有10G空间,每个月10G的下载流量,对于个人用户用于做个小博客,小网站来说,已经够了。

但是,七牛的官方开发文档真心会看得一头雾水。

于是,先记录下来这次传图的过程。

在上传图片之前,需要准备两样东西:

  1. AccessKey
  2. SecretKey

其中, AccessKey 和 SecretKey 能在 个人中心 > 秘钥管理中获得,如图。

  1. 创建空间 并 创建配置文件
  2. 选择 资源主页 ,再选择 立即添加,或者选择 对象存储 ,然后选择 添加
  3. 然后填上空间的名字,选择区域即可。
  4. 其中,空间的名字是我们使用代码上传至七牛服务器的第三个参数 Bucket
  5. 可以将这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');
  1. 获取上传凭证
  2. 上传凭证的作用:

客户端上传前需要先从服务端获取上传凭证,并在上传资源时将上传凭证作为请求内容的一部分。不带凭证或带非法凭证的请求将返回 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>"
}
  1. 如现有如下上传策略:
 $putPolicy = array(
 'scope' => QINIU_BUCKET.':'.$filename ,
 	'deadline' => time()+3600 ,
 	'returnBody' => '{
 		"name": $(fname),
 "file_url": $(x:file_url)
 	}'
);
  1. 该上传策略定义了:
1. 指定了图片上传至`QINIU_BUCKET`存储空间中,同时,该token只允许文件名为 `$filename` 的文件上传。
2. token有效时间为1个小时。
3. 设置返回信息,返回上传的文件的文件名,和自定义参数中的 `file_url`
  1. 将上传策略序列化成为JSON格式:
  2. 用户可以使用各种语言的 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)
 }"
}'
  1. 对 JSON 编码的上传策略进行URL安全的Base64编码,得到待签名字符串:
  2. 官方给的demo代码为:
encodedPutPolicy = urlsafe_base64_encode(putPolicy)
  1. 运行之后,发现 urlsafe_base64_encode 这个函数是自定义的,估计相当于将 +,/号转换为 -,_
 function _urlsafe_base64_encode($str){
	$find = array('+', '/');
	$replace = array('-', '_');
	return str_replace($find, $replace, base64_encode($str));
}
  1. 使用SecretKey对上一步生成的待签名字符串计算HMAC-SHA1签名:
  2. 官方给的demo代码为:
sign = hmac_sha1(encodedPutPolicy, QINIU_SECRET_KEY)
  1. 然而, hmac_sha1 这个函数也不是php自带的。经过搜索发现,其实PHP5.1.2之后的版本内置了直接产生的函数,只是名字不一样罢了: hash_hmac,因此需要将这里修改为:
$sign = hash_hmac('sha1' ,$encodedPutPolicy, QINIU_SECRET_KEY, true);
  1. 第一个参数为哈希算法名(支持md5,sha256,haval160,4等,具体可到 hash_algos()中查询);第二个参数为需要进行哈希的信息;第三个参数为秘钥;第四个参数为输出格式(true为输出二进制,false为输出16进制)
  2. 对签名进行URL安全的Base64编码:
  3. 官方代码:
encodedSign = urlsafe_base64_encode(sign)
  1. 这里的 urlsafe_base64_encode 依然为上述的自定义函数。
  2. 将AccessKey、encodedSign 和 encodedPutPolicy 用英文符号 : 连接起来:
$uploadToken = QINIU_ACCESS_KEY . ':' . $encodedSign . ':' . $encodedPutPolicy
  1. 返回token至客户端
echo json_encode(array('token' => $uploadToken, 'key' => $filename, 'fileurl' => QINIU_DOMAIN));
  1. 这里返回了文件名和文件url,主要是因为,保证文件在七牛中的唯一性,和可以随时更改七牛的空间访问地址。
  2. 上传图片
  3. 使用js直接上传图片至七牛服务器他的过程为:
  4. 向服务器请求 uploadToken =>
  5. 获取 ‘uploadToken` 后上传图片 =>
  6. 上传成功,显示图片。
  7. 这里没有使用 zepto jquery 这种库,所以浏览器的兼容性为兼容 FormData 的现代浏览器
  8. 使用 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>
  1. 给上传文件的按钮绑定一个 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
 }
 })
}

最终实现

希望本文能帮助到您!

点赞+转发,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓-_-)

关注 {我},享受文章首发体验!

每周重点攻克一个前端技术难点。更多精彩前端内容私信 我 回复“教程”

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

欢迎 发表评论:

最近发表
标签列表