问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

HTTP 的 POST 参数提交和上传的不同与 Mojolicious 的实现

发布网友 发布时间:2022-04-12 20:09

我来回答

1个回答

热心网友 时间:2022-04-12 21:38

对于 HTTP 协议, 我们在使用 POST 上传的时候, 其实是有好几种不同的处理方式的, 所以对于客户端和服务器端, 也分别都有不同的处理. 正常普通的网页在提交参数上传到服务器的时候, 主要会根据内容的不同来使用不同的处理. 所体现在不同的地方在 Content-Type 的类型.

比如我们常常用 Mojolicious 处理这类接收到的参数和内容的时候, 会让很多人晕掉, 所以我在这, 基于协议的头, 来给大家介绍一下在参数和上传的时候有什么不同.

客户端, 比如浏览器网页中的 form 的表格的参数的不同, 客户端比如 Linux 命令行的 curl 的参数的不同和程序接口提交参数的不同, HTTP 协议在上传的时候, 大约会有三种不同, 这些体现在 Content-Type 的三种类型:

application/x-www-form-urlencoded
multipart/form-data
post 的 body 的内容
下面我们来详细介绍

1. application/x-www-form-urlencoded 默认

浏览器: 在 HTML 中 form 有个参数是 enctype 属性用于指定编码方式, 常用有前面讲的两种: application/x-www-form-urlencoded 和 multipart/form-data. 但默认的时候, 我们并不指定. 不指定的时候, 默认是 "application/x-www-form-urlencoded" , 所以其实, 我们平时都是使用的这种格式来提交数据. 因为是默认就不写出来了. 注意, 这个会对空格和特别的符号进行 url 的 encode.

程序: 我们现在以 Mojo::UserAgent 这个模块为例子, 我们提交一个参数 args 值为 test.

$ua->post('ht tp:/ /w ww.php-oa.co m/a/b' => form => { args => 'test'});
命令:

$curl -svo /dev/null -d "args=test" htt p:/ /w ww.php-oa.co m/a/b
HTTP 协议状态

这个时候所发送的 HTTP 的头和内容分别如下. body 中会存着参数, 会有一个特别的 Header.

-- Blocking request (ht tp:/ /w ww.php-oa.co m/a/b)
-- Connect (ht tp:ww w.php-oa.c om:80)
-- Client >>> Server (htt p://w ww.php-oa.c om/a/b)
POST /a/b HTTP/1.1
User-Agent: Mojolicious (Perl)
Connection: keep-alive
Content-Type: application/x-ww w-form-urlencoded
Accept-Encoding: gzip
Content-Length: 9
Host: www.php-oa.com

args=test
服务端接收方式

这个时候, 服务器会根据因为是 POST 的方法, 并且头部的 Content-Type: application/x-www-form-urlencoded 会去解析 body 的参数. 这样在 Mojolicious 服务器

post '/a/b' => sub {
my $self = shift;
my $foo = $self->param('args');
$self->render(text => "Hello from $foo.");
}
2. multipart/form-data 大文件, 媒体文件

对于比较大的, 有一些二进制数据和象视频文件之类大文件, 建议使用这种方式上传.

浏览器:

普通的 HTTP 的写法如果要使用 enctype 的话, 只要象下面一样就行.

<form action="/path/to/login" enctype="multipart/form-data">
<input disabled="disabled" name="first_name" type="text" />
<input value="Ok" type="submit" />
</form>
客户端:

在 Mojo::UserAgent 考虑得非常周全, 当你提交的内容中包含二进制文件之类时, 就会自动帮你转换成 "multipart/form-data" 格式提交. 这个格式会生成一个随机字符来分割不同参数. 区分是否使用这种格式主要是, 当你提交的参数中, 又是一个引用, 并且引中可以使用 content 来指定内容或者 file 来指定路径.

$ua->post('htt p:/ /w ww.php-oa.c om/a/b' => form => { args => 'test', args_file => { file => '/root/.bash_history' } });

# or
$ua->post('ht tp://w ww.php-oa.c om/a/b' => form => { args => 'test', args_file => { content => 'test' } });
HTTP 协议状态

这个地方我们可以见到 Content-Type: multipart/form-data 的请求头, 告诉文件和参数是这种格式上传过来的.并且 boundary 用于指定一个参数之间的分割符.

-- Blocking request (ht tp://w ww.php-oa.c om/a/b)
-- Connect (ht tp:w ww.php-oa.co m:80)
-- Client >>> Server (ht p://ww w.php-oa.co m/a/b)
POST /a/b HTTP/1.1
User-Agent: Mojolicious (Perl)
Content-Type: multipart/form-data; boundary=WRoHX
Connection: keep-alive
Accept-Encoding: gzip
Content-Length: 14428
Host: www.php-oa.com

--WRoHX
Content-Disposition: form-data; name="args"
test
--WRoHX
Content-Disposition: form-data; name="args_file"; filename=".bash_history"
........文件本身
服务器接收方式

在后端的服务器接收的时候 Mojolicious 想得非常周到. 对于这种格式能自动解析, 并且全程异步.不会多占内存. 这个会自动给大的文件使用一个叫 Mojo::Upload 的对象来处理, 我们可以通过 $self->req->upload('args_file'); 这个方法取得这个内容的对象, 这个内容的对象是Mojo::Asset::File 这个对象, 存文件和取大文件之类可以直接调用.

post '/a/b' => sub {
my $self = shift;
my $upload = $self->req->upload('args_file');
my $foo = $self->param('args');
$self->render(text => "Hello from $foo.");
}
3. POST 的 body 的内容

最后一种, 是有时我们做大文件上传, 和提交内容之类.这个时候, 整个 body 都是文件本体. 参数象 get 一样通过 url 传过去.

这个就不用抓头了, 没任何转换, 直接整个 body 是个大文件.

客户端提交:

我们来看看客户端在这个时候怎么上传送. 同样, 我们使用 Mojo::UserAgent 为例子.

my $ua = Mojo::UserAgent->new;
$ua->transactor->add_generator(stream => sub {
my ($transactor, $tx, $path) = @_;
$tx->req->content->asset(Mojo::Asset::File->new(path => $path));
});
$ua->post('ht tp://w ww.php-oa.co m/a/b' => stream => '/root/.bash_history' );
服务器接收

这个时候, 在服务器端怎么接收啦?

post '/a/b' => sub {
my $self = shift;
my $body = $self->req->body;
my $foo = $self->param('args');
$self->render(text => "Hello from $foo.");
}
这个, 我们直接取请求的 body 就可以了, 但这有个小问题, 这是这个文件上传完, 这个 body 会存着所有的文件, 比如这个上传的文件有 1G , 这个 1G 就都会占着内存. 这个情况, Mojolicious 并没有实现事件来根据块取文件. 晚点, 我有个有于大文件上传的文章, 会分享我在 Mojolicious 中实现异步以块方式存储文件. 这样用户上传多少, 我存多少, 并不会占用更多的内存.

好了整个三种方式都介绍完了, 大家一定注意区分哦 .
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
天秤男吃醋的八大表现 天秤座男生吃醋时的表现 人工授精之后注意什么 人授后需要卧床休息吗 ...经两个月没发工资了,我不想干了,老板不给钱怎么办? 新手玩《兰斯10》这款游戏的快速通关攻略是什么? 兰斯10怎么用食券快速刷SSR 兰斯10二周目7cp怎么达成 兰斯10大侵攻达成条件介绍 跳舞同手同脚叫什么来着 喷油嘴清洗机主要功能 Excel中小写日期如何转大写日期? 用CAD怎么画变压器平面图 请大神讲解一下画yd5,yd7的变压器接线图步骤。 请问怎么快速学会用AUTOCAD 2010画电气图纸(比如交流一次接线图),急求指教啊! 变压器,断路器等怎么画 怎么根据变压器所给的连接组别,画出一二次的接线图和相量图? 变压器的三维图怎么画 WORD里面怎么画变压器 microsoft word97-2003文档里怎么画电力变压器图标和电杆图标 怎么用CAD画变压器图纸? 兴业银行信用卡积分兑换的网站是什么? 凉拌紫甘蓝的营养价值 苹果6s内存是emmc还是nvme 每代的iPhone的闪存规格算什么水平,与三星USF3.0有多大差距 如何评价iPhone 6s用的是NVMe闪存?相比ufs2.0如何? 凉拌紫甘蓝的功效 苹果xs max的闪存是ufs3.0吗 UFS3.0闪存,苹果手机11promax用的是这个吗? iphone12闪存是ufs3.1吗 CMA认证书编号后的字母是什么意思 ? 黄金认证书是什么样 开关电源变压器的结构图用什么软件画?? 安徽省界首市最近几天天气怎么样 如何获取变压器图纸 求高手,在Excel中怎样将小写变成大写。 excel转换支票日期大小写(按支票规范转换),C 列输入公式,格式见图 滁州天气6.3到10天气 小写转大写的函数格式? 扬子壁挂炉显示屏上的小风扇不转 壁挂炉哪个牌子经济实用耐用,扬子,阿里斯顿,欧能,卡莱曼,万和,瑞马;卡莱曼质量不错 170平米的家需要作多大的扬子壁挂炉多少元 扬子江天然气壁挂炉,打开水龙头后不点火,电池是新换的,这是什么情况?求解答!谢谢 扬子壁挂炉故障代码e7如何自己检修图 求问近义词辨别 illiterate ,unlettered 扬子壁挂炉显示屏shang图标的含义 weareilliterate什么意思? 高手来译:illiterate cultures什么意思? 薪酬的几个基本功能是什么? illiterater america 演讲 求illiterater america 这篇演讲文章,英汉都有的 英语语法解释:Through an illiterate woman who ...