我正在通过Rust直接下载MP3音频流。由于此流是不确定的,因此我希望能够尽早取消它以保存到目前为止已下载的内容。目前,我是通过按CTRL + C来停止程序的。这将产生一个stream.mp3文件,然后我可以播放和收听,虽然可以,但是并不理想。
给出以下代码,我怎么能以编程方式尽早停止io::copy()
并使其保存文件而不杀死整个程序?
extern crate reqwest;
use std::io;
use std::fs::File;
// Note that this is a direct link to the stream, not a webpage with HTML and a stream
const STREAM_URL: &str = "http://path.to/stream";
fn main() {
let mut response = reqwest::get(STREAM_URL)
.expect("Failed to request mp3 stream");
let mut output = File::create("stream.mp3")
.expect("Failed to create file!");
io::copy(&mut response, &mut output)
.expect("Failed to copy mp3 stream to file");
}
正如评论所述,io::copy
是一种便捷功能,用于完全读取Reader
并将其内容写入Writer
,而无需在中间停顿;它用于当您[[not关心中间状态,但只希望将整个内容从读取器传送到写入器时使用。
response
中获得前几Kb,则可以使用io::Read::take,它将Reader
限制为您指定的任何限制。它将返回一个新的Reader
,您可以将其传递给io::copy
。是的,您可以在任意位置剪切MP3文件。这是一种帧格式,虽然您很可能会破坏最后一帧,但实际上,所有mp3解码器都可以处理此帧。
// `Read` needs to be in scope, so .take() is available on a `io::Read`
use std::io::Read;
use std::io;
use std::fs::File;
fn main() {
let mut response = reqwest::get(STREAM_URL)
.expect("Failed to request mp3 stream")
.take(100*1024); // Since `Response` is `Read`, we can `take` from it.
let mut output = File::create("stream.mp3")
.expect("Failed to create file!");
// `response` is a limited reader, so it will only read 100kb before
// returning EOF, signaling a successful completion to `copy`.
io::copy(&mut response, &mut output)
.expect("Failed to copy mp3 stream to file");
}