最近在开发一个工具站时,我遇到了一个看似简单却让人头疼的问题:文件大小转换。
问题背景
平时开发中,我们经常需要处理文件大小。比如:
- 上传限制是 50MB,但服务器返回的是 bytes
- 日志文件显示 1.2GB,但我想知道这是多少 MB
- 设计稿标注的图片尺寸是 800KB,但实际文件是 819200 bytes
这些都是很常见的需求,但每次都要打开计算器或者搜索引擎,属实麻烦。
更烦的是,文件大小有两种不同的计量标准:
- SI(十进制):1 KB = 1000 Bytes(存储设备厂商常用)
- IEC(二进制):1 KiB = 1024 Bytes(操作系统常用)
这两种标准在数值上会有些差异,特别是当文件较大时。比如一个 1TB 的硬盘,在 Windows 上显示可能是 931GB(IEC 标准),而厂商宣传的是 1TB(SI 标准)。
传统解决方式的不足
以前我的做法是:
- 打开搜索引擎搜索"文件大小转换"
- 找到一个在线工具
- 用完后关掉,下次再用又得重新找
这种方式有几个痛点:
- 重复劳动:每次都要搜索、打开、使用
- 缺乏统一性:不同工具的显示格式不统一,有些还带广告
- 没有复制功能:很多时候需要复制结果,但很多工具不支持
决定自己开发
既然有这些痛点,为什么不自己写一个呢?作为一个独立开发者,我决定用 AI 辅助开发一个文件大小转换工具。
需求定义
首先,我明确了需求:
- 支持 SI 和 IEC 两种标准
- 输入任意数值,自动转换到所有单位
- 支持自定义精度
- 支持文件上传(拖拽或点击)
- 每行结果可独立复制
- 中英文切换
- 深色模式
AI 辅助开发过程
我使用 Claude 来辅助开发。第一次对话时,我给出了比较详细的需求描述:
diff
你是一名资深前端工程师。请根据下方规格,生成一个独立的单文件 HTML 工具。
- 工具 ID: file-size-converter
- 功能: 文件大小转换
- 支持 SI 和 IEC 两种标准
- 输入任意值后自动显示所有单位的换算结果
- 支持文件上传获取大小
- 支持复制结果
- 支持中英文切换
- 支持深色模式
Claude 第一次生成的代码整体框架不错,但有几个问题:
问题 1:单位列表不完整
第一次生成的代码只包含 B、KB、MB、GB,缺少 TB、PB 以及 IEC 标准的 KiB、MiB 等。
问题 2:精度处理不够优雅
原始代码直接使用 toFixed(precision),但这样会在显示时出现尾随零。比如 1.50 这样的结果,看起来不够简洁。
问题 3:复制功能没有降级方案
原始代码只用了 navigator.clipboard,但在某些浏览器(特别是非 HTTPS 环境)下会失败。
针对这些问题,我和 Claude 进行了多轮对话调优。
关键技术决策
1. 单位定义
javascript
var SI_UNITS = [
{ key: 'B', factor: 1 },
{ key: 'KB', factor: 1e3 },
{ key: 'MB', factor: 1e6 },
{ key: 'GB', factor: 1e9 },
{ key: 'TB', factor: 1e12 },
{ key: 'PB', factor: 1e15 }
];
var IEC_UNITS = [
{ key: 'B', factor: 1 },
{ key: 'KiB', factor: 1024 },
{ key: 'MiB', factor: 1048576 },
{ key: 'GiB', factor: 1073741824 },
{ key: 'TiB', factor: 1099511627776 },
{ key: 'PiB', factor: 1125899906842624 },
{ key: 'EiB', factor: 1152921504606847000 }
];
关键点是 factor 值直接用数字表示,而不是用 Math.pow() 动态计算。这样做的原因是:
- 性能更好(避免重复计算)
- 数值更精确(避免浮点误差累积)
- 代码更直观
2. 精度处理
javascript
var display = converted === 0 ? '0' : converted.toFixed(precision);
// Remove trailing zeros for cleaner display
if (display.indexOf('.') > 0) {
display = display.replace(/\.?0+$/, '');
}
这个处理很关键。toFixed(precision) 会保留指定小数位,但尾随零看起来不够简洁。比如 1.50 应该显示为 1.5。
正则表达式 /\.?0+$/ 的作用是:
\.?:匹配可选的小数点0+:匹配一个或多个零$:匹配字符串结尾
这样 1.50 → 1.5,2.00 → 2,3.140 → 3.14。
3. 复制功能的降级方案
javascript
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(...)
} else {
// Fallback to execCommand
var ta = document.createElement('textarea');
ta.value = text;
document.body.appendChild(ta);
ta.select();
document.execCommand('copy');
document.body.removeChild(ta);
}
这个降级方案很重要。navigator.clipboard API 需要 HTTPS 环境,在 localhost 或某些内网环境下可能不可用。
4. 人类可读格式
javascript
function humanReadable(bytes) {
if (bytes === 0) return '0 B';
var units = getUnits();
for (var i = units.length - 1; i >= 0; i--) {
if (bytes >= units[i].factor) {
var v = bytes / units[i].factor;
var str = v.toFixed(2);
str = str.replace(/\.?0+$/, '');
return str + ' ' + tu('units.' + units[i].key);
}
}
// ...
}
这个功能会找到最适合的单位来显示。比如 1,500,000 bytes 会显示为 1.5 MB,而不是 1500 KB。
踩坑记录
坑 1:浮点精度问题
在处理大数时,JavaScript 的浮点精度会出问题。比如:
javascript
1e15 + 1 === 1e15 // true,因为 1e15 超出了安全整数范围
解决方案是:避免对大数进行加减运算,只做乘除。乘除运算在大多数情况下都能保持足够的精度。
坑 2:文件大小可能为 0
上传一个空文件时,file.size 为 0。代码中要处理这种情况:
javascript
if (bytes === 0) return '0 B';
否则 0 / 1024 会得到 0,但显示时会有问题。
坑 3:输入值为负数
用户可能输入负数,虽然这不合理,但代码要能处理:
javascript
if (isNaN(val) || val < 0) {
results.innerHTML = '';
return;
}
直接清空结果,不显示任何转换值。
AI 辅助开发的感受
这次开发过程让我对 AI 辅助编程有了更深的体会:
-
AI 适合做框架,不适合做细节:Claude 生成的代码框架很好,但在边界情况处理、用户体验细节上需要自己补足。
-
prompt 要具体:第一次对话时,我给出的需求不够详细,导致生成的代码缺少一些功能。后来我补充了详细的功能列表和交互细节,生成的代码质量明显提升。
-
多轮对话是必要的:不可能一次对话就得到完美代码。需要和 AI 反复交流,指出问题,提出改进,才能得到满意的结果。
-
AI 教我的:在调优过程中,Claude 教了我一些技巧,比如正则表达式去尾随零、降级方案处理等。
实现细节
国际化
使用轻量级的 i18n 方案,内置中英文:
javascript
var I18N = {
zh: { title: "文件大小转换", ... },
en: { title: "File Size Converter", ... }
};
通过 navigator.language 自动检测语言,也支持 URL 参数 ?lang=en 手动指定。
深色模式
使用 CSS 变量和 prefers-color-scheme 媒体查询:
css
:root {
--bg: #fff;
--text: #111827;
/* ... */
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a2e;
--text: #e2e8f0;
/* ... */
}
}
这样用户系统的深色模式会自动适配,无需手动切换。
响应式布局
最小宽度 320px,在移动端会自适应:
css
@media (max-width: 480px) {
.input-group {
flex-direction: column;
align-items: stretch;
}
.input-group input[type=number] {
width: 100%;
}
}
适用场景
这个工具适合以下场景:
- 开发调试:查看日志文件大小、分析上传限制等
- 日常办公:处理设计稿、视频、文档等文件大小
- 存储规划:估算备份、迁移等场景下的存储需求
- 教学演示:向学生展示不同存储单位之间的换算
总结
这个工具的开发过程让我体会到:
- 小工具也有大讲究:看似简单的功能,实际开发中要考虑很多边界情况
- AI 辅助开发是趋势:AI 能帮你快速搭建框架,但细节还需要自己把控
- 用户体验很重要:一个简单的复制按钮,也需要考虑各种浏览器的兼容性
如果你也有类似需求,可以在线体验:文件大小转换工具
这个工具完全免费,支持中英文,支持深色模式,在手机上也能正常使用。