使用hyper将块流异步写入文件 [英] Writing a chunk stream to a file asynchronously using hyper

查看:74
本文介绍了使用hyper将块流异步写入文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个简单的函数,该函数使用hyper将远程文件下载到本地文件路径.我还需要文件写入也要异步(就我而言,我正在使用 tokio_fs ).这是代码:

I am trying to create a simple function that downloads a remote file to a local filepath using hyper. I need the file write to be asynchronous as well (in my case I am using tokio_fs for that). Here is the code:

在操场上查看

// 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 future返回的文件中,因此我在给定的示例中不了解如何解决此问题.

Conceptually, I understand what the error means: Since a FnMut captures variables by mutable reference, I cannot move a captured variable. However, I do not understand how can I work around this problem in the example given, since I need to write the stream to the file returned by the Join future.

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

The write_all method from the Write trait would work here since it takes the file as a mutable reference, but the problem is that it does the writing on the same thread.

推荐答案

您不想使用 for_each . io :: write_all 消耗目标和缓冲区,以换取将来将在完成后返回目标和缓冲区的将来.您可以将其与 Stream结合使用::fold 重用文件:

You do not want to use for_each. io::write_all consumes the target and the buffer in exchange for a future that will return the target and the buffer when it is done. You can combine this with Stream::fold to reuse the file:

.fold(file, |file, chunk| {
    io::write_all(file, chunk)
        .map(|(f, _c)| f)
        .map_err(|_| DownloadFileError::FileWrite)
})
.map(drop)

另请参阅:

这篇关于使用hyper将块流异步写入文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆