从MongoDB手册:
默认情况下,所有数据库字符串都是UTF8.要保存图像,二进制文件和其他非UTF8数据,可以将字符串作为对数据库的引用传递.
我正在抓取页面并希望存储内容以供以后处理.
Encode(不知道原来的charset)as flow of bytes(二进制数据)以供以后处理我的代码片段:
sub save {
my ($self, $ok, $url, $fetchtime, $request ) = @_;
my $rawhead = $request->headers_as_string;
my $rawbody = $request->content;
$self->db->content->insert(
{ "url" => $url, "rhead" => \$rawhead, "rbody" => \$rawbody } ) #using references here
if $ok;
$self->db->links->update(
{ "url" => $url },
{
'$set' => {
'status' => $request->code,
'valid' => $ok,
'last_checked' => time(),
'fetchtime' => $fetchtime,
}
}
);
}
Run Code Online (Sandbox Code Playgroud)
但得到错误:
子程序条目中的宽字符位于/opt/local/lib/perl5/site_perl/5.14.2/darwin-multi-2level/MongoDB/Collection.pm第296行.
这是我存储数据的唯一地方.
问题:在MondoDB中存储二进制数据的唯一方法是使用base64对它们进行编码吗?
这看起来又是一个关于_utf8_国旗的悲伤故事……
headers_as_string我可能是错的,但 HTTP::Message 的方法似乎将content其字符串作为字符序列返回。但是 MongoDB 驱动程序期望作为“二进制文件”显式传递给它的字符串是八位位组的序列 - 因此出现了警告戏剧。
一个相当丑陋的修复是在代码中取消utf8$rawhead 和 $rawbody 上的标志(我想知道它不应该由 MongoDB 驱动程序本身完成吗?),通过这样的事情......
_utf8_off $rawhead;
_utf8_off $rawbody; # ugh
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用encode('utf8', $rawhead)- 但你应该decode在从数据库中提取值时使用,我怀疑它不会更丑陋。