如何使用Mojo::UserAgent通过PUT方法上传大文件(非标量方式)?
用Mojo::UserAgent流式PUT上传大文件
嘿,你找对路子了!Mojo::UserAgent天生就支持流式上传大文件,完全不用把整个文件读到内存里。你已经尝试用Mojo::Asset::File了,这个方向是对的,只是可能在请求构造和细节上需要调整下,我给你梳理下几种靠谱的实现方式:
方法1:使用Mojo::Asset::File(推荐)
Mojo::Asset::File就是专门为处理大文件设计的,它会自动分块读取文件内容,不会一次性加载整个文件到内存。下面是优化后的代码:
use strict; use warnings; use Mojo::UserAgent; use Mojo::Asset::File; my $ua = Mojo::UserAgent->new; my $file = $ARGV[0]; die("File not found") unless (-f $file); # 创建文件资产对象,默认采用流式读取 my $asset = Mojo::Asset::File->new(path => $file); # 构造PUT请求:URL -> 请求头 -> 流式请求体 my $tx = $ua->put( 'https://postman-echo.com/put', { 'X-Test' => '123G', # 根据你的文件类型设置正确的Content-Type,比如text/plain、image/png等 'Content-Type' => 'application/octet-stream' }, $asset ); # 处理响应结果 if ($tx->success) { print "请求成功!\n"; print "响应内容:\n" . $tx->result->body . "\n"; } else { my $err = $tx->error; print "请求失败:" . $err->{message} . "\n"; print "状态码:" . $err->{code} . "\n" if $err->{code}; } # 可选:查看发送的请求详情 print "\n发送的请求文本:\n" . $tx->req->text . "\n";
关键细节:
- 一定要设置匹配文件类型的
Content-Type,服务器才能正确解析你上传的内容;如果不确定文件类型,用application/octet-stream通用二进制类型也可以。 Mojo::Asset::File还支持设置chunk_size参数调整每次读取的块大小(默认是131072字节,也就是128KB),比如Mojo::Asset::File->new(path => $file, chunk_size => 65536)。
方法2:直接使用文件句柄
如果你不想额外引入Mojo::Asset::File,直接用Perl原生的文件句柄也能实现流式上传:
use strict; use warnings; use Mojo::UserAgent; my $ua = Mojo::UserAgent->new; my $file = $ARGV[0]; die("File not found") unless (-f $file); # 打开文件句柄,二进制模式避免编码问题 open my $fh, '<:raw', $file or die "无法打开文件:$!"; # 用文件句柄作为请求体 my $tx = $ua->put( 'https://postman-echo.com/put', { 'X-Test' => '123G', 'Content-Type' => 'application/octet-stream' }, $fh ); close $fh; # 后续响应处理和上面的代码一致...
Mojo会自动从文件句柄逐块读取内容,实现流式上传,和Mojo::Asset::File效果一样。
方法3:如果需要multipart/form-data格式的PUT请求
虽然PUT请求通常直接传文件内容,但有些API可能要求用表单格式上传,这时可以用Mojo::FormData来构建请求,同样是流式处理:
use strict; use warnings; use Mojo::UserAgent; use Mojo::FormData; my $ua = Mojo::UserAgent->new; my $file = $ARGV[0]; die("File not found") unless (-f $file); # 构建表单数据,添加文件字段 my $form = Mojo::FormData->new; $form->add( 'uploaded_file', # 表单字段名 { file => $file, filename => 'my_large_file.dat' # 可选:指定文件名 } ); # 发送PUT请求 my $tx = $ua->put( 'https://postman-echo.com/put', {'X-Test' => '123G'}, $form ); # 响应处理同上...
总结
你的初始思路完全正确,用Mojo::Asset::File或者文件句柄都是处理大文件PUT上传的最优解,核心就是利用Mojo的流式处理能力,避免把大文件加载到内存里。只要确保请求头设置正确,就能顺利完成上传啦!
内容的提问来源于stack exchange,提问作者Pradeep
相关产品推荐
相关产品推荐

