宝塔主机管理 里面的文件管理功能做的不错,支持压缩包上传解压,但是距离自己想要的还差一步,所以就有了这个书签小工具。
利用 FileAPI.js
获取 拖拽的文件或目录 直接上传,并且保持与本地同步的目录结构。
Piecon.js
用 Favicon 来显示进度
虽然说是书签小工具,为了方便也可以写成 Userscript
- 2022-04-18 修复对宝塔 7.9.0 支持
- 7.9.0 版本 宝塔添加了对 拖拽上传的支持,但是 有 BUG, 如果拖拽上传文件后,文件浏览器切换到其他目录 拖拽上传还是 会 上传到第一次的目录。返回来想用这个脚本发现不能用了, 所有就有了本次更新
- 2019-10-08 使用 6.9.8 版本 宝塔时候发现不能用了所以更新了下
javascript:(function(){
/*@ 宝塔文件管理 6.9.8 批量拖拽上传工具 **/
// 20220420 修改 对 7.9.0 的支持
var initDndUpload = function(){
this.getScript = this.getScript || 0;
if(this.getScript > 3){return}
if(typeof FileAPI == 'undefined' || typeof Piecon == 'undefined'){
return create('script', {
src: 'https://cdn.asilu.com/fileapi.js,piecon.js',
onload: initDndUpload
}, 'head');
}
function create(tag, attr, to){
var dom = document.createElement(tag);
var setAttr = function(dom, attr){
for(var k in attr){
if(typeof attr[k] == 'object'){
setAttr(dom[k], attr[k]);
}else{
dom[k] = attr[k];
}
}
};
if(typeof attr == 'object'){
setAttr(dom, attr)
}
document[to == 'head' ? to : 'body'].appendChild(dom);
return dom;
}
var $path = document.querySelector('#fileInputPath');
if(!$path || window.initDndUploadLoaded){return}
/* 阻止重复加载 */
window.initDndUploadLoaded = 1;
var $mask = create('div', {style:{
display: 'none',
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100vh',
background: 'rgba(0,0,0,.5)',
lineHeight: '100vh',
textAlign: 'center',
zIndex: 9999999,
fontSize: '50px',
color: '#fff',
}, innerText: '释放立马上传'});
/* 版本 6.9.8 token 支持 */
var token = document.querySelector('#request_token_head');
var headers = token ? {
'x-http-token': token.getAttribute('token'),
'x-cookie-token': getCookie('request_token')
} : {};
// 移除 7.9.0 自带上传层
let oldView = document.querySelector('#uploadView');
if(oldView){
oldView.remove();
}
FileAPI.event.dnd(window, function(over) {
$mask.style.display = over ? 'block' : 'none';
}, function(files) {
if (files.length) {
var totalSize = 0;
var filesInfo = files.map(function(a){
totalSize += a.size;
return a.fullPath.padEnd(30) + a.size;
});
var path = typeof $path.dataset.path != 'undefined' ? $path.dataset.path : $path.value;
if(confirm(['确认上传', files.length, '个文件到', path, ', 共', totalSize].join(' ') +'\n'+ filesInfo.join('\n'))){
console.log(path);
loopUpload(files, path);
}
}
});
function loopUpload(files, path, index){
index = index || 0;
if(index < files.length){
var file = files[index];
Piecon.setProgress((index + 1) / files.length * 100);
console.log((index + 1) +'/'+ files.length +': '+ path + file.fullPath);
upload(file, path + file.fullPath.slice(0, -file.name.length), function(ok){
if(ok !== false){
index++;
loopUpload(files, path, index);
}
});
}else{
if(typeof GetFiles == 'function'){
GetFiles(path);
}else if(bt_file && typeof bt_file.reader_file_list == 'function'){
bt_file.reader_file_list({path: path});
}
Piecon.reset();
}
}
function upload(file, path, call){
/* 兼容新版 TOKEN */
return FileAPI.upload({
url: '/files?action='+ (token ? 'upload' : ('UploadFile&path='+ encodeURIComponent(path) +'&codeing=byte')),
files: token ? { blob: file } : { zunfile: file },
data: !token ? {} : {f_path: path, f_name: file.name, f_size: file.size, f_start: 0},
headers: headers,
complete: function(err, xhr) {
if (!err) {
call.call(xhr, xhr.responseText);
}else{
call.call(xhr, false);
}
}
});
}
};
initDndUpload();
})();