nexusphp
nexusphp copied to clipboard
对 `files` 表进行优化建议
在上传种子的时候,如果种子包含的文件数过多,会对 files
表产生大量 insert 操作,并在用户检索对应种子文件列表的时候,select 操作传输过多数据。此外, files
表中 filename
列在文件较深的情况下,会产生大量重复字段。
以上,建议对 files
表进行优化,直接在 files 表中存入树状结构的 json 文本,并在检索种子文件列表操作时直接返回数据库文本即可。实测能解决部分种子上传超时问题。
存入的 json 结构如下:
对于单文件种子:
{
"torrentName": { // 种子名
"file1": 12345678 // 文件+大小
}
}
对于多文件种子:
{
"torrentName": { // 种子名
"Dir1": { // 子文件夹
"file1": 12345678, // 文件+大小
},
"file2": 12345678,
"file3": 12345678
}
}
此处提供部分 patch (因为完整的未形成展示性 pr )
- 对 files 表结构进行修改(或另建一个表)
- 文件
takeupload.php
进行修改
/** 前面需要把 $filelist 从 Array<Array<string,string>> 变成 Dict<string,string>
// 修改前
$filelist[] = array($dname, $totallen);
$filelist[] = [$ffe, $ll];
// 修改后
$filelist[$dname] = $totallen;
$filelist[$ffe] = $ll;
*/
// after get torrent id
// 生成新的files表
function getFileTree($array, $delimiter = '/')
{
if (!is_array($array)) {
return [];
}
$splitRE = '/' . preg_quote($delimiter, '/') . '/';
$returnArr = [];
foreach ($array as $key => $val) {
// Get parent parts and the current leaf
$parts = preg_split($splitRE, $key, -1, PREG_SPLIT_NO_EMPTY);
$leafPart = array_pop($parts);
// Build parent structure
// Might be slow for really deep and large structures
$parentArr = &$returnArr;
foreach ($parts as $part) {
if (!isset($parentArr[$part])) {
$parentArr[$part] = [];
} elseif (!is_array($parentArr[$part])) {
$parentArr[$part] = [];
}
$parentArr = &$parentArr[$part];
}
// Add the final part to the structure
if (empty($parentArr[$leafPart])) {
$parentArr[$leafPart] = $val;
}
}
return $returnArr;
}
$fileTreeJson = getFileTree($filelist);
if ($type === "multi") {
$fileTreeJson = [$dname => $fileTreeJson];
}
// then insert $fileTreeJson to database after json_encode
- 前端 viewfilelist 优化,并提供折叠功能:
// 代码取自 OurBits /assets/js/common.js ,需要适配修改
function build_tree(tree,par = '') {
let ret = '';
for (let k in tree) {
let v = tree[k];
let dep = (par.match(/\//g) || []).length;
if (typeof v == 'object') {
ret += "<tr " +(par === "" ? "" : "style='display:none' data-par = \"" + par + "\" ")+ "><td class='rowfollow' data-name='" + k + "'>" + " ".repeat(dep * 2) + "<a href='javascript: void(0);'><b>" + k +"</b></a></td>";
ret += build_tree(v,par + "/" + k);
} else {
ret += "<tr " +(par === "" ? "" : "style='display:none' data-par = \"" + par + "\" ")+"><td class=rowfollow data-name='" + k + "'>" + " ".repeat(dep * 2) + k + "</td><td class=rowfollow align='right' data-size='"+ v + "'>" + humanFileSize(v, 2) + "</td></tr>";
}
}
return ret;
}
function viewfilelist(torrentid) {
$.post('api.php', {'action': 'viewfiletree', 'tid': torrentid}, function (data) {
if (data.success) {
document.getElementById("showfl").style.display = 'none';
document.getElementById("hidefl").style.display = 'block';
var file_list = data.files;
var file_list_html = "<table class=\"main\" border=\"1\" cellspacing=0 cellpadding=\"5\">";
file_list_html += "<tr><td class=colhead>Path</td><td class=colhead align=center><img class=\"size\" src=\"../../pic/trans.gif\" alt=\"size\" /></td></tr>";
file_list_html += build_tree(file_list);
file_list_html += "</table>";
document.getElementById("filelist").innerHTML = file_list_html;
$('#filelist a').click(function () {
let that = $(this);
let parent = that.parents('tr:eq(0)');
let par = parent.attr('data-par');
let expand = (par ? par: "") + "/" + that.text();
$('#filelist tr[data-par^="'+ expand +'/"]').hide(); // 首先隐藏所有对应子项
$('#filelist tr[data-par$="'+ expand +'"]').toggle(); // 然后对当前项可见性进行切换
})
} else {
alert(data.msg);
}
});
}
- 提供平滑迁移功能(此处不做展示)
感谢建议,优化部分延后一些。
鉴于 Rhilip/Bencode 库的更新,建议直接使用其提供的 Rhilip\Bencode\TorrentFile 来替换整个种子解析过程。具体可见 https://github.com/Rhilip/NexusPHP/commit/346374e9836a049b4d6bbbd21f003560cb64642d