kityminder
Version:
282 lines (231 loc) • 8.34 kB
JavaScript
/* global fio:true, jQuery: true */
/**
*
* @fileOverview
*
* 为 FIO 提供网盘 IO 支持
*
* @author techird
*
* 使用网盘的 IO,需要:
*
* 1. 在 http://dev.baidu.com 上创建应用。创建应用后,就有相应的 API Key
* 2. 设置登录回调地址为使用的页面,设置位置:其他API -> 安全设置
* 3. 申请 PCS API 权限
*
*/
/* TODO: 脱离 jQuery 依赖 */
(function(window, $) {
/**
* 用到的 URL 地址
*/
var urls = {
/**
* PCS API 接口
*
* @see http://developer.baidu.com/wiki/index.php?title=docs/pcs/rest/file_data_apis_list
*/
'file': 'https://pcs.baidu.com/rest/2.0/pcs/file'
};
/**
* 网络请求
*/
function ajax(opt) {
opt.cache = false;
return new Promise(function(resolve, reject) {
$.ajax(opt).done(resolve).fail(reject);
});
}
/**
* 延时执行
*/
function wait(delay) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve();
}, delay);
});
}
// 转换 PCS 的文件数据为 fio.file.File
function pcs2file(pcs_file) {
var file = new fio.file.File(pcs_file.path);
file.createTime = new Date(pcs_file.ctime * 1000);
file.modifyTime = new Date(pcs_file.mtime * 1000);
file.size = pcs_file.size;
file.isDir = !!pcs_file.isdir;
file.provider = 'netdisk';
return file;
}
function getMeta(path) {
var user = fio.user.current();
var access_token = user && user.access_token;
if (!access_token) throw new Error('Not Authorized');
function request() {
return ajax({
url: urls.file,
data: {
method: 'meta',
access_token: access_token,
path: path
},
dataType: 'json'
})['catch'](function(e) {
if (request.retry++ > 2) throw e;
return new Promise(function(resolve) {
setTimeout(function() {
resolve(request());
}, 200 * request.retry);
});
});
}
request.retry = 0;
return request();
}
// 根据文件请求分发处理
function handle(request) {
var user = fio.user.current();
var access_token = user && user.access_token;
if (!access_token) throw new Error('Not Authorized');
var param = {};
// 默认参数
var opt = {
url: urls.file,
type: 'GET',
dataType: 'JSON'
};
// 处理其他参数
switch (request.method) {
case fio.file.METHOD_ACL_READ:
case fio.file.METHOD_ACL_WRITE:
throw new Error('Not Supported File Request:' + request.method);
case fio.file.METHOD_READ:
opt.dataType = request.dataType;
param.method = 'download';
break;
case fio.file.METHOD_WRITE:
opt.type = 'POST';
param.method = 'upload';
param.ondup = request.dupPolicy == fio.file.DUP_OVERWRITE ? 'overwrite' : 'newcopy';
var form = new FormData();
if (request.data.type == fio.file.TYPE_BLOB) {
form.append('file', request.data.content);
} else {
form.append('file', new Blob([request.data.content], {
type: 'text/plain'
}));
}
opt.data = form;
opt.processData = false;
opt.contentType = false;
break;
case fio.file.METHOD_LIST:
param.method = 'list';
break;
case fio.file.METHOD_MKDIR:
opt.type = 'POST';
param.method = 'mkdir';
break;
case fio.file.METHOD_MOVE:
opt.type = 'POST';
param.method = 'move';
param.to = request.newPath;
if (request.dupPolicy == fio.file.DUP_RENAME) {
param.ondup = 'newcopy';
}
break;
case fio.file.METHOD_DELETE:
opt.type = 'POST';
param.method = 'delete';
break;
}
// 处理 path 参数
if (request.method == fio.file.METHOD_MOVE) {
param.from = request.path;
} else {
param.path = request.path;
}
// 参数拼接到 URL 中
opt.url += '?' + $.param(param) + '&access_token=' + access_token;
// 重试次数
var retry = request.extra.retry === undefined ? 3 : parseInt(request.extra.retry, 10);
var failed = 0;
function tryRequest() {
// 捕捉到错误后重试或抛异常
function retryOrThrow(e) {
window.console.warn('PCS Fail(' + (++failed) + '): ', {
request: request,
error: e
});
if (retry--) {
return wait(1000 * failed).then(tryRequest);
} else {
e.requestMethod = request.method;
e.requestPath = request.path;
e.requestUser = request.user && request.user.username || null;
e.requestParam = param;
if (request.dataType)
e.requestDataType = request.dataType;
throw e;
}
}
function success(response) {
function meta2pcs(meta) {
return meta.list[0];
}
// 调用失败
if (response.error_code) {
throw new fio.FileRequestError(response);
}
// 读取操作需要抓取文件元数据后返回
if (request.method === fio.file.METHOD_READ) {
return getMeta(param.path).then(meta2pcs).then(pcs2file).then(function(file) {
file.data = new fio.file.Data(response);
return file;
});
}
// 列文件返回
if (request.method == fio.file.METHOD_LIST) {
return response.list.map(pcs2file);
}
// 移动文件返回
if (request.method == fio.file.METHOD_MOVE) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(getMeta(response.extra.list[0].to).then(meta2pcs).then(pcs2file));
}, 200);
});
}
// 删除文件返回
if (request.method == fio.file.METHOD_DELETE) {
return new fio.file.File(request.path);
}
var file = pcs2file(response);
// 写文件返回
if (request.method === fio.file.METHOD_WRITE) {
file.data = request.data;
}
return file;
}
function fail($xhr) {
var response = $xhr.responseText;
var responseInfo = {
readyState: $xhr.readyState,
status: $xhr.status,
statusText: $xhr.statusText,
headers: $xhr.getAllResponseHeaders(),
responseText: response
};
if (response) try {
responseInfo.detail = JSON.parse(response);
} catch (ignore) {}
return retryOrThrow(new fio.FileRequestError(responseInfo));
}
return ajax(opt).then(success, fail);
}
return tryRequest();
}
// 网盘 IO 提供实现
fio.provider.register('netdisk', {
handle: handle
});
})(window, jQuery);