【问题标题】:Why is a PNG image downloaded by reqwest corrupt? [duplicate]为什么reqwest下载的PNG图像损坏? [复制]
【发布时间】:2020-09-14 20:00:08
【问题描述】:

我正在按照 https://rust-lang-nursery.github.io/rust-cookbook/web/clients/download.html 的 Rust Cookbook 中提到的代码通过 HTTP GET 请求以异步方式下载文件。

我的代码如下:

#[tokio::main]
async fn main() -> Result<()> {

    let object_path = "logos/rust-logo-512x512.png";
    let target = format!("https://www.rust-lang.org/{}", object_path);  
    let response = reqwest::get(&target).await?;

    let mut dest = {
    
        let fname = response
            .url()
            .path_segments()
            .and_then(|segments| segments.last())
            .and_then(|name| if name.is_empty() { None } else { Some(name) })
            .unwrap_or("tmp.bin");
            
            
        println!("file to download: '{}'", fname);

        let object_prefix = &object_path[..object_path.rfind('/').unwrap()];
        let object_name = &object_path[object_path.rfind('/').unwrap()+1..];
        let output_dir = format!("{}/{}", env::current_dir().unwrap().to_str().unwrap().to_string(), object_prefix);
        fs::create_dir_all(output_dir.clone())?;

        println!("will be located under: '{}'", output_dir.clone());
                
        let output_fname = format!("{}/{}", output_dir, object_name);
        println!("Creating the file {}", output_fname);
        
        File::create(output_fname)?
        
    };
    let content =  response.text().await?;
    copy(&mut content.as_bytes(), &mut dest)?;
    Ok(())
}

它创建目录并下载文件。 但是,当我打开文件时,它显示损坏的文件错误 我也尝试过使用其他一些 URL,但损坏的文件问题仍然存在

我在代码中遗漏了什么吗?

【问题讨论】:

  • 您正在以文本形式下载响应,因此它自然不会工作,因为 PNG 文件是二进制文件。
  • 使用bytes 而不是text
  • 我试过let content = response.bytes().await?; copy(&amp;mut content, &amp;mut dest)?; 但它给出了错误``` copy(&mut content, &mut dest)?;没有为 bytes::bytes::Bytes ``` 实现特征 std::io::Read
  • @test,使用io::Cursor

标签: rust async-await http-get reqwest


【解决方案1】:

只使用bytesCursor 也可以,而且更简单:

let mut content =  Cursor::new(response.bytes().await?);
copy(&mut content, &mut dest)?;

【讨论】:

    【解决方案2】:

    更换

    let content =  response.text().await?;
    copy(&mut content.as_bytes(), &mut dest)?;
    

    通过

    let content =  response.bytes().await?;
        
    let mut pos = 0;
    while pos < content.len() {
        let bytes_written = dest.write(&content[pos..])?;
        pos += bytes_written;
    }
    

    成功了! :)

    如果此代码效率低,请回复 感谢大家的帮助。

    【讨论】:

    • 使用write_all: dest.write_all (&amp;content)?; 比手动循环更简单。