Запись потока чанка в файл асинхронно с использованием гипер - PullRequest
0 голосов
/ 16 ноября 2018

Я пытаюсь создать простую функцию, которая загружает удаленный файл в локальный путь к файлу с помощью гипер.Мне нужно, чтобы запись в файл также была асинхронной (в моем случае я использую tokio_fs для этого).Вот код:

Вид на игровую площадку

// 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.

Метод write_all из Write черта будет работать здесь, поскольку он принимает файл в качестве изменяемой ссылки, но проблема в том, что он выполняет запись в том же потоке.

1 Ответ

0 голосов
/ 16 ноября 2018

Вы не хотите использовать for_each.io::write_all потребляет цель и буфер в обмен на будущее, которое вернет цель и буфер, когда это будет сделано.Вы можете комбинировать это с Stream::fold для повторного использования файла:

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

См. Также:

...