页面直接上传文件至七牛云空间(结合 layui upload组件)
使用页面直传至七牛云存储,结合layui组件举例说明
导火索
页面上传至七牛云最常采用的方式是“页面 -> 服务器 -> 七牛云”,也就是前端先上传至服务器,然后后端进行上传至七牛云,这样做的好处时,中断率出错率会相对比较低,但如果时比较大的文件,那简直就浪费时间,整个过程会非常慢,在此同时会消耗服务器资源,带宽占用、负载变大等,这样非常不友好;
然而我们可以直接采用页面直传至七牛云,即“页面 -> 七牛云”,这样对应上传大文件来说,只要客户端网络好,上传就很快,但这时消耗的客户端资源,也就说若客户端配置较差有可能会导致卡顿等;
一、“页面 -> 七牛云”上传
1、 后端需提供七牛云上传token,注意每次上传token都不一样,所以每次上传需更新token;
以PHP为例,以下是七牛云 PHP SKD 官方文档 ,其他语言对应的文档可打开后在左边菜单栏选择
关键步骤为
use \Qiniu\Auth;
$accessKey = "QINIU_ACCESS_KEY"
$secretKey = "QINIU_SECRET_KEY"
$bucket = "your bucket name"
// 初始化Auth状态
$auth = new Auth($accessKey, $secretKey);
$expires = 3600;
$filename = 'mp4/qiniu.mp4';//上传至七牛云空间的路径与名称
$policy = null;//自定义需返回的参数
$upToken = $auth->uploadToken($bucket, $filename, $expires, $policy, true);
需特别注意上面的 filename 这个名字必须与前端使用七牛云JSSDK上传传入的名字一致
2、 前端将文件直接使用七牛云JSSDK 上传至七牛云
JavaScript SDK 官方文档
https://developer.qiniu.com/kodo/1283/javascript
关键步骤
- 引入js 文件
支持以下几种安装方式
- 直接使用静态文件地址
https://cdnjs.cloudflare.com/ajax/libs/qiniu-js/<version>/qiniu.min.js
// 当上方资源链接访问不稳定时,可选使用下方资源链接
https://cdn.staticfile.org/qiniu-js/<version>/qiniu.min.js
通过 script 标签引入该文件,会在全局生成名为 qiniu 的对象
<version>为版本号,具体可以查看版本信息 https://github.com/qiniu/js-sdk/releases
eg:https://cdn.staticfile.org/qiniu-js/3.3.3/qiniu.min.js
另外此处有坑,注意需引入JQ,且对JQ版本有要求,需jquery-3.3.1.min.js或以上版本,不然可能报错“require.js:8 Uncaught Error: Mismatched anonymous define() module: function(){return function(t){var e={};function n®”
- 使用 NPM 安装
NPM 的全称是 Node Package Manager,是一个 NodeJS 包管理和分发工具,已经成为了非官方的发布 Node 模块(包)的标准。如果需要更详细的关于 NPM 的使用说明,您可以访问 NPM 官方网站,或对应的 中文网站
npm install qiniu-js
const qiniu = require(‘qiniu-js’)
// or
import * as qiniu from ‘qiniu-js’
- 通过源码编译
git clone git@github.com:qiniu/js-sdk.git,进入项目根目录执行 npm install ,执行 npm run build,即可在dist 目录生成 qiniu.min.js。
- 引入 js 后会生成全局 qiniu 对象,接下来就是使用这个对象进行上传
最关键的代码
//file上传文件
//filename 上传至七牛云的文件名称要与上面提到的生成token的文件名称一致
//token 上传token 一般向后端获取
//putExtra 额外的参数,详情请参考文档
//config 配置信息 ,详情请参考文档
qiniu.upload(file, filename, token, putExtra, config);
3、实战(使用 layui upload组件)
- 上传html (省略不必要的 html 代码)(以下代码仅供参考)
<button type="button" class="layui-btn" id="uploader_button">
<i class="layui-icon"></i>上传图片
</button>
<script>
layui.config({
base: ''
}).extend({
qiniuyun: "../qiniuyun/index",//引入自己写的七牛云上传组件
}).use(['qiniuyun', 'layer', 'upload', 'form', 'element'], function(){
var upload = layui.upload
, form = layui.form
, element = layui.element
,layer = layui.layer
,qiniuyun = layui.qiniuyun
;
//执行upload组件实例
uploadInst = upload.render({
elem: '#uploader_button' //绑定元素
,accept: "*/*" //允许上传的文件类型
,field: "file" //设定文件域的字段名
,acceptMime: "*/*"
,auto: false//选择文件后不自动上传
,progress: function(n, elem, res, index){
if (n >= 100) {
thisPercentUpdate(100);
thisPercent = 50;
}
var percent = (Number(n) / 2) + '%' //获取进度百分比
element.progress('file_uploader_progress', percent); //可配合 layui 进度条元素使用
},
choose: function (obj) {
thisPercent = 0;
updateThisPercent = 0;
$("#file_uploader_progress_div").show();
element.progress('file_uploader_progress', "0%");
layer.load(); //上传loading
$("#content").val("");
$("#file_original_name").val("");
$("#upload_success_file_div").hide();
$("#upload_success_file_name").html("未上传或上传失败 ~ ");
$("#file_uploader_button").removeClass('layui-btn-fz');
$("#file_uploader_button").css("background-color", "#009688");
$("#upload_success_file_name").css("color", "#000000");
if (selectType === 1 || 1) {
//start
var files = obj.pushFile(), thisStart = 0, keysArray = Object.keys(files);
if (files && keysArray.length > 0) {
keysArray.forEach(function(key) {
if (thisStart === keysArray.length - 1) {
let index = key
, file = files[key]
, resultObj = files[key]
;
let requestData = {}, thisFilename;
if (file && file.name) {
thisFilename = file.name;
requestData = {filename: thisFilename};
}
$.ajax({
url: "your get qiniuyun token api url",
type: "POST",
data: requestData,
dataType: "json",
success: function (result) {
let thisData = result.data;
if (result.code === 1 && thisData && thisData.token) {
qiniuyun.loader({
domain: thisData.domain // 后台设置的域名项
, elem: "#file_uploader_qi_niu" // 绑定的element
, token: thisData.token // 授权token
, retryCount: 6 // 重连次数,默认6(可选)
, fileNamePath: thisData.path
, fileNameUniQid: thisData.uniqid
, fileName: thisData.fileName
, originalName: thisData.originalName
, fileExt: thisData.fileExt
, validExt: thisData.ext
, validMaxSzie: thisData.maxSize
, thisFile: file
, thisObj: file
// , region: qiniu.region.z2 // 选择上传域名区域,默认自动分析(可选)
, next: function(response){
element.progress('file_uploader_progress', response.total.percent + '%'); // 进度条
}, error(err){
thisPercent = 0;
updateThisPercent = 100000;
$("#file_uploader_progress_div").hide();
element.progress('file_uploader_progress', "0%");
$("#upload_success_file_div").show();
$("#upload_success_file_name").html("上传失败了,请重新上传 ~ ");
$("#uploader_span").html("重新上传");
$("#file_uploader_button").addClass('layui-btn-fz');
$("#file_uploader_button").css("background-color", "#ba1535");
$("#upload_success_file_name").css("color", "#ba1535");
layer.alert(err, {title: "上传失败提示", icon: 2,})
layer.closeAll('loading'); //关闭loading
},complete: function(res){//上传成功
thisPercent = 100;
updateThisPercent = 100000;
element.progress('file_uploader_progress', "100%");
$("#content").val(thisData.domain+"/"+res.key);
$("#upload_success_file_div").show();
$("#upload_success_file_name").html(thisFilename);
$("#file_original_name").val(thisFilename);
$("#uploader_span").html("重新上传");
$("#file_uploader_button").addClass('layui-btn-fz');
$("#upload_success_file_name").css("color", "rgba(26,112,215,0.6)");
isUploader = 1;
layer.msg("上传成功 ~",{icon: 1, time: 1500}, function () {
$("#file_uploader_progress_div").hide();
})
layer.closeAll('loading'); //关闭loading
}
});
} else {
thisPercent = 0;
updateThisPercent = 100000;
$("#file_uploader_progress_div").hide();
element.progress('file_uploader_progress', "0%");
$("#upload_success_file_div").show();
$("#upload_success_file_name").html("上传失败了,请重新上传 ~ ");
$("#uploader_span").html("重新上传");
$("#file_uploader_button").addClass('layui-btn-fz');
$("#file_uploader_button").css("background-color", "#ba1535");
$("#upload_success_file_name").css("color", "#ba1535");
layer.alert("【tokenERROR2】网络异常,请重试 ~ ", {title: "上传失败提示", icon: 2,})
layer.closeAll('loading'); //关闭loading
}
},
error: function () {
thisPercent = 0;
updateThisPercent = 100000;
$("#file_uploader_progress_div").hide();
element.progress('file_uploader_progress', "0%");
$("#upload_success_file_div").show();
$("#upload_success_file_name").html("上传失败了,请重新上传 ~ ");
$("#uploader_span").html("重新上传");
$("#file_uploader_button").addClass('layui-btn-fz');
$("#file_uploader_button").css("background-color", "#ba1535");
$("#upload_success_file_name").css("color", "#ba1535");
layer.alert("【tokenERROR1】网络异常,请重试 ~ ", {title: "上传失败提示", icon: 2,})
layer.closeAll('loading'); //关闭loading
}
});
} else {
layer.msg("上传时发生异常,请重试 ~ ", {icon: 2, time: 1500});
}
thisStart++;
});
}
}
}
,error: function(){
thisPercent = 0;
updateThisPercent = 100000;
$("#file_uploader_progress_div").hide();
element.progress('file_uploader_progress', "0%");
$("#upload_success_file_div").show();
$("#upload_success_file_name").html("上传失败了,请重新上传 ~ ");
$("#uploader_span").html("重新上传");
$("#file_uploader_button").addClass('layui-btn-fz');
$("#file_uploader_button").css("background-color", "#ba1535");
$("#upload_success_file_name").css("color", "#ba1535");
layer.alert("网络异常,请重试 ~ ", {title: "上传失败提示", icon: 2,})
layer.closeAll('loading'); //关闭loading
}
});
});
</script>
- 自己的七牛云上传组件(以下代码仅供参考)
var checkDomain = 0;//是否校验七牛空间(bucket)对应的域名
layui.define('layer', function(exports){
var $ = layui.$,layer = layui.layer, thisFileNamePath = "", thisFileNameUniQid = "";
exports('qiniuyun', {
loader:function (options,callback) {
let thisBase = "https://cdn.staticfile.org/qiniu-js/3.3.3/qiniu.min.js" //七牛云js
,thisJqUrl = "https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js" //JQ
;
$.getScript(thisJqUrl,function () {//动态加载JQ 务必先加载JQ
console.log(thisJqUrl)
$.getScript(thisBase,function () { //动态加载七牛云JS
//console.log(qiniu);// 可先尝试是否获取到 qiniu 对象
if(!options.token){
layer.msg('初始化参数:token不能为空.', {icon: 2});
return;
}
if(checkDomain && !options.domain){
layer.msg('初始化参数:域名不能为空.', {icon: 2});
return;
}
if (options.fileNamePath) {
thisFileNamePath = options.fileNamePath;
console.log(thisFileNamePath)
}
if (options.fileNameUniQid) {
thisFileNameUniQid = options.fileNameUniQid;
console.log(thisFileNameUniQid)
}
var token = options.token
, domain = options.domain
, config = {
useCdnDomain: true, //是否使用加速域名
disableStatisticsReport: false, //是否禁用日志报告
retryCount: options.retryCount || 6,
debugLogLevel: "INFO",
region: options.region || qiniu.region.z2
}
, putExtra = {
fname: "",
params: {},
mimeType: null
}
, thisFile
, thisObj
, thisValidExt
, thisFileNamePath
, thisFileNameUniQid
, thisFileName
, thisOriginalName
, thisFileExt
, thisValidMaxSzie
;
if (options.thisFile) {
thisFile = options.thisFile;
}
if (options.thisObj) {
thisObj = options.thisObj;
}
if (options.validExt) {
thisValidExt = options.validExt;
}
if (options.fileName) {
thisFileName = options.fileName;
}
if (options.fileNamePath) {
thisFileNamePath = options.fileNamePath;
}
if (options.fileNameUniQid) {
thisFileNameUniQid = options.fileNameUniQid;
}
if (options.originalName) {
thisOriginalName = options.originalName;
}
if (options.vlidMaxSzie) {
thisValidMaxSzie = options.vlidMaxSzie;
}
if (options.fileExt) {
thisFileExt = options.fileExt;
}
if (!thisFileExt) {
let OriginalFileName = thisFile.name;
let thisFileExt = OriginalFileName.split('.').pop();
}
if (!thisFile || !thisObj) {
options.error("文件选择失败,请重试 ~ ");
return;
}
let this_filename = thisFile.name
, this_file_size = thisFile.size
, this_file_type = thisFile.type
;
if (!this_filename || !this_file_size || this_file_size <= 0) {
console.log("this_filename this_file_size ");
console.log(this_filename);
console.log(this_file_size);
options.error("文件选择失败,请重试 ~ ");
return;
}
if (thisValidExt.indexOf(thisFileExt) === -1) {
options.error("文件不符合类型 ~ ");
return;
}
if (thisValidMaxSzie < this_file_size) {
options.error("文件超出最大限制 ~ ");
return;
}
if (!thisFileName) {
thisFileName = thisFileNamePath
+ this_filename.substring(0, this_filename.lastIndexOf("."))
+ "_"
+ thisFileNameUniQid
+ thisFileExt;
}
var error = function(err) {
if(typeof options.error === 'function'){
options.error(err);
}else{
options.error("上传失败:"+JSON.stringify(err));
}
};
var complete = function(res) {
if(typeof options.complete === 'function'){
options.complete(res);
}else{
options.complete("上传成功:"+JSON.stringify(res));
}
};
var next = function(response) {
if(typeof options.next === 'function'){
console.log("function")
options.next(response);
}else{
var chunks = response.chunks || [];
var total = response.total;
// 这里对每个chunk更新进度,并记录已经更新好的避免重复更新,同时对未开始更新的跳过
for (var i = 0; i < chunks.length; i++) {
if (chunks[i].percent === 0 || finishedAttr[i]) {
continue;
}
if (compareChunks[i].percent === chunks[i].percent) {
continue;
}
if (chunks[i].percent === 100) {
finishedAttr[i] = true;
}
}
console.log("上传进度:" + total.percent + "% ");
compareChunks = chunks;
}
};
observable = qiniu.upload(thisObj, thisFileName, token, putExtra, config);
var subObject = {next:next,error:error,complete:complete};
if(typeof callback === 'function'){
callback(observable,subObject)
}else{
observable.subscribe({next:next,error:error,complete:complete});
}
});
});
}
})
});
技术要点
1、 引入直接写的七牛云上传组件
· 动态先后加载JQ(若之前已加载过JQ可无需再次加载)、加载七牛云JSSDK【并非一定得动态加载,在html中直接引用也可】
· 关键代码为:qiniu.upload(file, filename, token, putExtra, config); 务必注意filename 必须与请求token的名称一致,否则会鉴权失败报403;PS: qiniu.upload 会自动判断是否需分片上传,无需过多处理;
2、加载layui组件,需引入直接写的七牛云组件,使用 layui.config 引入
· upload.render 需关闭自动上传(即auto: false)
· 上传逻辑使用 upload.render 中的 choose 回调函数,在该函数内进行直接上传或按钮上传
二、 “页面 -> 服务器 -> 七牛云” 上传(简单讲述下)
1、页面上传文件至服务器
若采用layui upload组件可参考以下代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>upload模块快速使用</title>
<link rel="stylesheet" href="/static/build/layui.css" media="all">
</head>
<body>
<button type="button" class="layui-btn" id="test1">
<i class="layui-icon"></i>上传图片
</button>
<script src="/static/build/layui.js"></script>
<script>
layui.use('upload', function(){
var upload = layui.upload;
//执行实例
var uploadInst = upload.render({
elem: '#test1' //绑定元素
,url: '/upload/' //上传接口
,done: function(res){
//上传完毕回调
}
,error: function(){
//请求异常回调
}
});
});
</script>
</body>
</html>
2、后端接收文件临时保存至服务器,再使用七牛云提供的SKD进行上传至七牛云
以PHP为例,以下是七牛云 PHP SKD 官方文档 ,其他语言对应的文档可打开后在左边菜单栏选择
关键步骤为
// 引入鉴权类
use Qiniu\Auth;
// 引入上传类
use Qiniu\Storage\UploadManager;
// 需要填写你的 Access Key 和 Secret Key
$accessKey ="your accessKey";
$secretKey = "your secretKey"
$bucket = "your bucket name";
// 构建鉴权对象
$auth = new Auth($accessKey, $secretKey);
// 生成上传 Token
$token = $auth->uploadToken($bucket);
// 上传文件临时保存的路径
$filePath = './php-logo.png';
// 上传至七牛云存储后保存的文件名
$key = 'my-php-logo.png';
// 初始化 UploadManager 对象并进行文件的上传。
$uploadMgr = new UploadManager();
// 调用 UploadManager 的 putFile 方法进行文件的上传。
list($ret, $err) = $uploadMgr->putFile($token, $key, $filePath, null, 'application/octet-stream', true, null, 'v2');
echo "\n====> putFile result: \n";
if ($err !== null) {
var_dump($err);
} else {
var_dump($ret);
}
3、上传完成后删除服务器中所上传的原文件(易忽略)
完结~
更多推荐
所有评论(0)