2

我正在使用 PerlWWW::Mechanize下载一个 MP3 文件,该文件以 400KB 的块(大约 20 秒)提供。

当我binmode在文件句柄上保存数据时,在每个块到达时附加它,只有第一个块被正确播放;其余的不是。

当我不使用时binmode,我无法播放整个文件——它会播放但听起来很有趣!

这是我的程序

use WWW::Mechanize;

$agent = WWW::Mechanize->new( cookie_jar => {} );

@links = ("http://thehost.com/chunk1","http://thehost.com/chunk2","http://thehost.com/chunk3");

foreach (@links){
    $agent->get($_);

    my $filename = 'test.mp3';
    open(my $fh, '>>', $filename) or die "Could not open file '$filename' $!";
    binmode $fh;
    print $fh $agent->content;
    close $fh;
}

我究竟做错了什么?

更新

这些是返回的 HTTP 标头。

Cache-Control: public
Connection: close
Date: Tue, 28 Oct 2014 18:38:37 GMT
Pragma:
Server: Apache
Content-Length: 409600
Content-Type: application/octet-stream
Expires: Sat, 24 Oct 2015 12:08:00 GMT
Access-Control-Allow-Origin: *
Client-Date: Tue, 28 Oct 2014 18:38:28 GMT
Client-Peer: **.**.***.***:80
Client-Response-Num: 1
4

3 回答 3

1

我怀疑单个 mp3 文件只是在一定数量的字节后被拆分,然后这些块作为单独的下载提供。相反,我假设这些都是单独的 mp3 文件,其中包含 20 秒的原始文件,并且每个 URL 都包含一个正确的 mp3 文件。因为 mp3 不是数据,而是标题和数据,所以您不能通过将它们连接在一起来简单地合并这些 mp3 文件。相反,您必须使用 ffmpeg 之类的程序从多个 mp3 文件创建单个 mp3 文件,请参阅https://superuser.com/questions/314239/how-to-join-merge-many-mp3-files

于 2014-10-28T18:03:07.533 回答
1

我怀疑内容的标头不正确,并且当您使用自动解码的 API 时,这会破坏八位字节流。

请改用该mirror方法并在下载后连接文件。

于 2014-10-28T17:56:35.783 回答
1

我无法解释您得到的行为,但WWW::Mechanize它适用于 HTML 文本页面,并且不适用于二进制数据。直接使用LWP::UserAgent模块一点也不难。

我建议你改用这样的东西。

use strict;
use warnings;
use 5.010;
use autodie;

use LWP;

my @links = qw(
  http://thehost.com/chunk1
  http://thehost.com/chunk2
  http://thehost.com/chunk3
);

my $agent = LWP::UserAgent->new;

my $filename = 'test.mp3';
open my $fh, '>:raw', $filename;

for my $link (@links) {
    my $resp = $agent->get($link);
    die $resp->status_line unless $resp->is_success;
    print $fh $resp->decoded_content;
}

close $fh;

如果您仍然有问题,请添加这样的行

print $resp->headers_as_string, "\n\n";

通话后get立即报告,并报告您获得的结果。

您也可以通过使用content方法而不是decoded_content.

当然,如果您能提供真实的 URL,它可能对我们有很大帮助,但我知道您可能无法做到这一点。

于 2014-10-28T18:15:53.470 回答