Perl与MongoDB二进制数据

7
来自MongoDB手册:

默认情况下,所有数据库字符串均为UTF8。要保存图像、二进制数据和其他非UTF8数据,您可以将字符串作为对数据库的引用传递。

我正在获取页面并希望将内容存储以供以后处理。

  • 我不能依赖meta-charset,因为许多页面具有utf8内容,但错误地声明为iso-8859-1或类似的格式
  • 因此,我不能使用Encode(不知道原始字符集)
  • 因此,我想将内容简单地存储为字节流(二进制数据),以备以后处理

我的代码片段:

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,
            }
        }
    );
}

但是出现了错误:

在/opt/local/lib/perl5/site_perl/5.14.2/darwin-multi-2level/MongoDB/Collection.pm的第296行,子例程中的宽字符。

这是我存储数据的唯一地方。

问题是:在MondoDB中存储二进制数据的唯一方法是将其编码,例如使用base64吗?


如果您将$rawhead$rawbody设置为手册中给出的示例(即"\xFF\xFE\xFF"),它是否会发出相同的警告? - raina77ow
2个回答

3

看起来又是关于_utf8_标志的悲惨故事...

我可能错了,但似乎HTTP::Message的headers_as_stringcontent方法返回字符串作为一个字符序列。但MongoDB驱动程序希望传递给它的字符串明确地表示为'二进制序列',因此出现了警告。

比较丑陋的解决方法是在您的代码中取消$rawhead和$rawbody上的utf8标志(我想也许应该由MongoDB驱动程序自己完成?),类似于以下内容...

_utf8_off $rawhead; 
_utf8_off $rawbody; # ugh

另一种选择是使用encode('utf8', $rawhead) - 但是在从数据库中提取值时应该使用decode,我怀疑这样做会更丑陋。

0

你的数据是字符,而不是八位字节。你的假设似乎是你只是将东西作为八位字节传递,但你必须早些时候违反了这个假设,可能甚至在你没有注意到的情况下解码了传入的文本数据。

因此,简单地不要解码,数据保持八位字节,存储到数据库中就不会失败。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接