使用Hyper异步地将块流写入文件

3
我正在尝试使用hyper创建一个简单的函数,将远程文件下载到本地路径中。我需要文件写入也是异步的(在我的情况下,我使用tokio_fs)。以下是代码:

在playground中查看

// Parts of the code were omitted, see the playground for full source code
pub fn download_file(
    uri: Uri,
    file_location: &Path,
) -> Box<Future<Item = (), Error = DownloadFileError>> {
    let temp_dir_path = tempfile::tempdir().unwrap().into_path();
    let file_name = match file_location.file_name() {
        Some(file_name) => file_name,
        None => return Box::new(futures::failed(DownloadFileError::IncorrectFilePath)),
    };

    let temp_filepath = temp_dir_path.join(&file_name);

    let connector = HttpsConnector::new(2).unwrap();
    let client: Client<_, Body> = Client::builder().build(connector);

    let response_future = client
        .get(uri)
        .map_err(|err| DownloadFileError::GetRequest(err));

    let create_file_future =
        File::create(temp_filepath).map_err(|err| DownloadFileError::CreateFile(err));

    Box::new(
        response_future
            .join(create_file_future)
            .and_then(move |(res, file)| {
                res.into_body()
                    .map_err(|e| DownloadFileError::GetRequest(e))
                    .for_each(move |chunk| {
                        io::write_all(file, chunk)
                            .map(|_| ())
                            .map_err(|_| DownloadFileError::FileWrite)
                    })
            }),
    )
}

然而,我遇到了以下错误:
error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
  --> src/lib.rs:79:39
   |
75 |             .and_then(move |(res, file)| {
   |                                   ---- captured outer variable
...
79 |                         io::write_all(file, chunk)
   |                                       ^^^^ cannot move out of captured outer variable in an `FnMut` closure

从概念上来说,我理解这个错误的含义:由于 FnMut 通过可变引用捕获变量,因此我无法移动捕获的变量。但是,在给定的示例中,我不明白如何解决这个问题,因为我需要将流写入 Join 未来返回的文件。

Write 特性的 write_all 方法可以在这里使用,因为它以文件的可变引用作为参数进行写入,但问题在于它在同一线程上执行写入操作。


我认为使用for_each()没有意义,into_body()返回一个选项,所以只需使用map()。但也许我完全错了,我不理解hyper/futures中的任何东西。 - Stargateur
据我理解,两者都使用write_all同步地写入文件。而在我的情况下,io::write_all也是异步完成的。 - lhahn
1个回答

4

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