You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:11:04