Mojolicious动态生成Tar归档文件无法打开问题求助
Tar归档文件可被识别但无法打开的问题排查与修复
我用Mojolicious实现了一个接口,允许用户下载指定目录下的所有文件为Tar归档包,部署在Caddy代理之后。虽然下载的文件被file命令识别为POSIX tar归档,但归档工具无法正常打开它。
原实现代码:
get '/admin/downloadmedia' => sub { my $c = shift; my $tar = Mojo::Tar->new; my $cb = $tar->files( [ glob('../files/*') ] )->create; warn Dumper( $tar->files ); my $drain; $drain = sub { my $me = shift; return $me->finish if ( $tar->is_complete ); my $chunk = $cb->(); $me->write( $chunk, $drain ); }; $c->res->content->headers->add( 'Content-Type', 'application/tar' ); $c->res->content->headers->add( 'Content-Disposition', 'attachment;filename=Zahaan-Bday-Media.tar' ); $c->$drain; };
文件识别结果:
$ file Downloads/Zahaan-Bday-Media\ \(1\).tar Downloads/Zahaan-Bday-Media (1).tar: POSIX tar archive
问题原因
流式写入逻辑错误:当$cb->()返回undef(表示Tar内容已生成完毕)时,代码仍尝试写入空内容,破坏了Tar归档的完整性;同时$tar->is_complete的判断时机错误,应该在获取chunk后检查而非之前。
修复后的代码
get '/admin/downloadmedia' => sub { my $c = shift; my $tar = Mojo::Tar->new; my $cb = $tar->files( [ glob('../files/*') ] )->create; my $drain = sub { my $me = shift; my $chunk = $cb->(); # 无更多内容则结束响应 return $me->finish unless defined $chunk; $me->write( $chunk, $drain ); }; # 改用Mojolicious标准方法设置响应头,避免重复添加 $c->res->headers->content_type('application/tar'); $c->res->headers->content_disposition('attachment;filename=Zahaan-Bday-Media.tar'); $c->$drain; };
修复说明
- 修正流式写入逻辑:先获取chunk,判断存在后再写入,无内容直接结束响应
- 用Mojolicious内置的
content_type和content_disposition方法设置响应头,更规范且避免重复添加 - 移除了调试用的
warn Dumper(如需调试可保留,生产环境建议删除)
内容的提问来源于stack exchange,提问作者Pradeep
相关产品推荐
相关产品推荐

