Mojolicious初学(十二)
一、文件上传
文件上传,是一个web框架必不可少的功能之一。我们经常需要收集访问者的一些文件,或者是电子版的一寸照片等情况。
当我们前端web网页请求中包括multipart/form-data头时,Mojolicious框架会依靠Mojo::Upload对象识别param中的上传文件。至于文件的大小,不必担心,超过250KB的文件,Mojolicious会自动缓存到一个临时文件中。
在使用上传文件的过程中,我们可以借助Mojolicious::Plugin::TagHelpers.中的form_for方便的在html模板中快速生成一个上传文件页面:
use Mojolicious::Lite -signatures;
# 这是一个上传文件的界面
get '/' => 'form';
# 这里是上传文件的处理过程
post '/upload' => sub ($c) {
# 检查上传文件的大小
return $c->render(text => 'File is too big.', status => 200) if $c->req->is_limit_exceeded;
# 处理上传的文件
return $c->redirect_to('form') unless my $example = $c->param('example');
my $size = $example->size;
my $name = $example->filename;
$c->render(text => "Thanks for uploading $size byte file $name.");
};
app->start;
__DATA__
@@ form.html.ep
<!DOCTYPE html>
<html>
<head><title>Upload</title></head>
<body>
%= form_for upload => (enctype => 'multipart/form-data') => begin #form_for后跟url,upload是其中一种写法,建议使用"/upload"这种形式更易于理解。
%= file_field 'example' #这里对应后端request param的键名
%= submit_button 'Upload' #‘Upload’代表按钮显示的名称
% end
</body>
</html>
二、User Agent
这里的User agent不仅仅是html中User agent概念,据我个人研究,Mojolicious中使用Mojo::UserAgent模块更加类似于Perl语言闻名遐迩的爬虫模块LWP::UserAgent。
也就是说,UserAgent在这里代表着内嵌的爬虫结构,可以爬取其他web网页。这种技术,主要的用途在于,api接口,我们可以与其他web系统进行接口集成:
use Mojolicious::Lite -signatures;
# 阻塞的、同步的
get '/headers' => sub ($c) {
my $url = $c->param('url') || 'https://mojolicious.org';
my $dom = $c->ua->get($url)->result->dom; #爬取'https://mojolicious.org'网页
$c->render(json => $dom->find('h1, h2, h3')->map('text')->to_array);
};
# 非阻塞、异步的
get '/title' => sub ($c) {
$c->ua->get('mojolicious.org' => sub ($ua, $tx) {
$c->render(data => $tx->result->dom->at('title')->text); #同上,异步方式
});
};
# 并发的
get '/titles' => sub ($c) {
my $mojo = $c->ua->get_p('https://mojolicious.org');
my $cpan = $c->ua->get_p('https://metacpan.org');
Mojo::Promise->all($mojo, $cpan)->then(sub ($mojo, $cpan) { #协程方式并发爬取两个网站
$c->render(json => {
mojo => $mojo->[0]->result->dom->at('title')->text,
cpan => $cpan->[0]->result->dom->at('title')->text
});
})->wait;
};
app->start;

