2026-09-25-预览面板文件名显示百分号编码修复.md

下载平台「预览界面文件名显示成百分号编码」修复记录

1. 现象

在下载中心点开可预览的文件时,右侧预览面板顶部的文件名显示为整串百分号编码,例如:

%E9%BB%91%E7%A5%9E%E8%AF%9D%E6%82%9F%E7%A9%BA%20%E5%A4%A7%E5%9C%A3%E6%88%98%E6%AD%8C%E3%80%8A%E4%BA%91%E5%AE%AB%E8%BF%85%E9%9F%B3%E3%80%8B%20%E8%B1%AA%E5%8D%8E%E5%85%B8%E8%97%8F%E6%97%A0%E6%8D%9F%E7%89%88%20%5BBV148sge8E8T%5D%20%5B4K60-HEVC%5D.mp4

(对应文件 dl-hub/53-B站视频下载/黑神话悟空 大圣战歌《云宫迅音》 豪华典藏无损版 [BV148sge8E8T] [4K60-HEVC].mp4)

整页预览(?preview=1)与移动端预览都是正常的,只有桌面版左右分栏的右侧面板标题异常——这一条是关键线索,说明服务端解码没问题(decodeURIComponent(u.pathname) 在 previewChrome() 里用 path.basename(filePath) 显示,一直是中文),问题出在前端 JS。

2. 根因

桌面列表页行模板里,data-name 属性只在目录可删除时才输出(listPage() 中的 delAttr 把 data-href / data-isdir / data-bytes / data-delmode 和 data-name 一起按 canDelete 门控):

// 修复前
const delAttr = canDelete ? ` data-name="${esc(d.name)}" data-isdir="0" ... ` : '';
return `<tr class="file-row"${kindAttr} data-href="${href}"${delAttr}>...`;

可删除区只有 09-迅雷下载(delete)和 用户上传(trash);dl-hub 下的普通子目录(如 53-B站视频下载)里 canDelete === false,于是行上没有 data-name,只有百分号编码的 data-href。

而前端 LIST_JS 打开预览面板时用的是:

var name = row.getAttribute('data-name') || href;   // 没有 data-name 就退化成 data-href
pTitle.textContent = name;                          // 面板标题 = encodeURIComponent(文件名)

data-href = encodeURIComponent(d.name),所以面板标题正好显示成用户看到的那串 %E9%BB%91...。这也解释了为什么「用户上传/09 区」里点开预览是正常的。

3. 修复(~/Downloads/download-server.js)

  1. listPage() 行模板:data-name 改为无条件输出,删除相关属性仍按 canDelete 门控,语义不变:
    • 文件行:<tr class="file-row" data-kind=… data-href=… data-name=… [data-isdir/data-bytes/data-delmode]>
    • 目录行:<tr class="dir-row" data-name=… [data-href/data-isdir/data-delmode]>
  2. 移动端列表行(mobileListPage())同样改为 data-name 恒输出。
  3. 三处 LIST_JS / UPLOAD_JS / MOBILE_DEL_JS 里的兜底逻辑加解码保险(防旧的缓存页面或将来漏写属性):
var name = row.getAttribute('data-name');
if (!name) { name = href; try { name = decodeURIComponent(name); } catch (err) {} }

(不动服务端的 URL 解码逻辑:URL 本身必须保持百分号编码,这是规范要求,不是 bug。)

4. 验证

5. 影响面与后续

下载此文件