1. 为什么需要切割大文件?
在企业IT运维工作中,经常会遇到需要将大型文件从Windows系统传输到Linux服务器的情况。比如部署容器镜像、迁移数据库备份、上传大型媒体资源等。我最近就遇到一个典型案例:需要将一个9GB的Docker镜像文件上传到受安全管控的Linux服务器。
直接上传这么大的文件会遇到几个典型问题:
- 网络传输不稳定导致中断,需要从头开始重传
- FTP客户端错误识别文件大小(比如把9GB识别成1.5GB)
- 传输过程中文件损坏无法验证
- 企业安全策略限制单个文件传输大小
实测发现,当文件超过2GB时,很多FTP客户端都会出现各种异常。这时候就需要用到二进制切割这个技术方案。简单说就是把大文件像切蛋糕一样分成若干小块,传输完成后再合并还原。
2. 文件切割的正确姿势
2.1 选择二进制切割而非文本切割
我第一次尝试时犯了个典型错误:用文本分割的方式处理二进制文件。结果合并后的tar.gz镜像文件总是报错损坏。后来才发现,压缩包、镜像这类二进制文件必须用字节级切割,不能按行分割。
Windows下最方便的切割工具就是PowerShell。下面这个脚本我优化过多次,现在已经成为我们团队的标配工具:
$sourceFile = "D:\bigfiles\app-image.tar.gz" $outputDir = "D:\bigfiles\split_parts" $chunkSize = 1GB # 建议1GB一个块 # 创建输出目录 New-Item -ItemType Directory -Force -Path $outputDir | Out-Null # 二进制读取源文件 $fs = [System.IO.File]::OpenRead($sourceFile) $buffer = New-Object byte[] $chunkSize $partNum = 1 try { while (($bytesRead = $fs.Read($buffer, 0, $buffer.Length)) -gt 0) { $outFile = Join-Path $outputDir ("part{0:D4}.bin" -f $partNum) $fos = [System.IO.File]::Create($outFile) $fos.Write($buffer, 0, $bytesRead) $fos.Close() Write-Host "生成分片: $outFile" $partNum++ } } finally { $fs.Close() }关键点说明:
- 使用
[System.IO.File]::OpenRead二进制读取 - 固定大小的字节数组作为缓冲区
- 分片后缀用.bin强调二进制属性
- 分片编号用4位数字(part0001.bin)方便排序
2.2 分片大小怎么选?
经过多次实测,推荐以下分片策略:
| 文件大小 | 推荐分片 | 原因 |
|---|---|---|
| <2GB | 不分割 | 避免额外开销 |
| 2-10GB | 1GB/片 | 平衡传输效率与容错 |
| >10GB | 500MB/片 | 降低单次传输失败成本 |
特别注意:某些旧版FTP服务对>2GB文件支持不好,这时要适当减小分片。
3. FTP传输的关键配置
3.1 必须使用二进制传输模式
这是我踩过最大的坑!很多FTP客户端默认使用ASCII模式传输,这会导致二进制文件损坏。以FileZilla为例,必须修改:
- 菜单栏:编辑 > 设置
- 选择"传输" > "FTP"
- 文件类型选择"二进制"
- 勾选"保持连接活动"
3.2 优化传输参数
在安全管控环境下,还需要调整几个关键参数:
# FileZilla配置示例 [Transfer] Timeout=0 # 禁用超时 RetryCount=10 # 增加重试次数 SendBuffer=8192 # 增大发送缓冲区 RecvBuffer=8192 # 增大接收缓冲区如果使用命令行工具,推荐用lftp:
lftp -u user,pass ftp.example.com <<EOF set net:timeout 60 set net:max-retries 10 set ftp:charset utf8 set ftp:passive-mode true mput /local/path/part*.bin EOF4. Linux端的合并与验证
4.1 正确的合并方式
所有分片上传到Linux服务器后,执行合并:
# 进入分片目录 cd /path/to/uploaded # 按数字顺序合并(确保part0001.bin在前) cat part*.bin > full-image.tar.gz # 校验文件完整性 tar -tzf full-image.tar.gz > /dev/null && echo "校验通过" || echo "文件损坏"4.2 高级校验技巧
对于特别重要的文件,建议在切割时生成校验码:
# 切割后为每个分片生成MD5 Get-ChildItem $outputDir | ForEach-Object { $hash = (Get-FileHash $_.FullName -Algorithm MD5).Hash "$($_.Name) $hash" | Out-File "$outputDir\checksums.md5" -Append }在Linux端验证:
md5sum -c checksums.md55. 常见问题排查指南
5.1 传输中断问题
现象:上传过程中频繁断开 解决方案:
- 检查网络MTU值(建议1500)
- 禁用FTP客户端的被动模式
- 调整TCP窗口大小
5.2 合并后文件损坏
现象:解压或加载时报错 排查步骤:
- 检查切割脚本是否使用二进制模式
- 确认FTP传输模式为二进制
- 对比原始文件和合并文件的MD5
- 测试单个分片是否能正确还原
5.3 性能优化技巧
当传输特大文件(50GB+)时,可以:
- 使用并行传输工具(如rsync)
- 先压缩再切割(节省带宽)
- 启用断点续传功能
最近一次迁移8TB的数据库备份时,我们先用7-zip分卷压缩,再用这个方案传输,总耗时从3天降到了18小时。关键是要根据实际网络环境调整分片大小和并发数。