我已经构建了一个概念验证,如果阅读器是包装在tokio_io::AsyncRead
使用FuturesAsyncReadCompatExt
的reqwest::async_impl::Response
,那么当在蜂窝/WiFi/有线网络之间切换时,tokio::io::copy
将永远挂起.
这发生在MacOS和iOS上,这是我可以访问的平台.
-
Full proof-of-concept code (GitHub)(只有
cargo run
)(更新:现在也包含修复/解决方法) - ProgressReadAdapter found here,但不是概念验证所必需的.
- Previous attempt at getting help个
- Further discussion on GitHub seanmonstar/reqwest个
#[tokio::main()]
async fn main() {
let mut target_file = std::env::current_dir().unwrap();
target_file.push("bbb.mp4");
println!("File will be downloaded to {target_file:?}");
let client = ClientBuilder::default()
// Doesn't seem to help
.tcp_keepalive(Some(Duration::from_secs(1)))
// Doesn't seem to help
.connect_timeout(Duration::from_secs(1))
.build()
.unwrap();
let response = client.get("http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_native_60fps_stereo_abl.mp4").send().await.unwrap();
match response_to_file(response, target_file).await {
Ok(_) => println!("Everything OK"),
Err(err) => eprintln!("{err}"),
}
}
async fn response_to_file(response: Response, path: PathBuf) -> Result<(), ApiError> {
let download = response.bytes_stream();
let download = download
.map_err(|e| futures::io::Error::new(futures::io::ErrorKind::Other, e))
.into_async_read();
let download = download.compat();
// Wrap download to be able to get progress in terminal
let mut download = ProgressReadAdapter::new(download);
let temp_file = tokio::task::spawn_blocking(NamedTempFile::new)
.await
.wrap_api_err()?
.wrap_api_err()?;
let mut outfile = tokio::fs::File::create(temp_file.path())
.await
.wrap_api_err()?;
// Code hangs here forever after a network switch
tokio::io::copy(&mut download, &mut outfile)
.await
.wrap_api_err()?;
outfile.flush().await.wrap_api_err()?;
let _persisted_file: File = tokio::task::spawn_blocking(move || temp_file.persist(path))
.await
.wrap_api_err()?
.wrap_api_err()?;
Ok(())
}
上面的代码中有一些概念,比如可以在GitHub上找到的wrap_api_err
,但我认为它们对于分析问题并不重要.
主要的问题是--在切换网络后,我如何才能用Err
退出response_to_file
?
第二个问题可能是-如果没有简单的方法来修复此代码,如何将网络资源的流副本复制到出现错误时实际干净地退出的临时文件?