Как распаковать ответ Reqwest / Hyper с использованием потоков? - PullRequest
0 голосов
/ 22 мая 2018

Мне нужно скачать 60 МБ ZIP-файл и извлечь единственный файл, который находится внутри него.Я хочу скачать и извлечь его с помощью потоков.Как я могу добиться этого с помощью Rust?

fn main () {
    let mut res = reqwest::get("myfile.zip").unwrap();
    // extract the response body to myfile.txt
}

В Node.js я бы сделал что-то вроде этого:

http.get('myfile.zip', response => {
  response.pipe(unzip.Parse())
  .on('entry', entry => {
    if (entry.path.endsWith('.txt')) {
      entry.pipe(fs.createWriteStream('myfile.txt'))
    }
  })
})

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

С помощью reqwest вы можете получить файл .zip:

reqwest::get("myfile.zip")

Поскольку reqwest можно использовать только для извлечения файла, ZipArchive из ящика zip можно использовать для его распаковки.Невозможно передать файл .zip в ZipArchive, так как ZipArchive::new(reader: R) требует R для реализации Read (что выполняется Response из reqwest) и Seek, что не реализовано Response.

В качестве обходного пути вы можете использовать временный файл:

copy_to(&mut tmpfile)

Как File реализует как Seek, так и Read, zip можно использовать здесь:

zip::ZipArchive::new(tmpfile)

Это рабочий пример описанного метода:

extern crate reqwest;
extern crate tempfile;
extern crate zip;

use std::io::Read;

fn main() {
    let mut tmpfile = tempfile::tempfile().unwrap();
    reqwest::get("myfile.zip").unwrap().copy_to(&mut tmpfile);
    let mut zip = zip::ZipArchive::new(tmpfile).unwrap();
    println!("{:#?}", zip);
}

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

0 голосов
/ 22 мая 2018

Вот так я бы прочитал файл hello.txt с содержимым hello world из архива hello.zip , расположенный на локальном сервере:

extern crate reqwest;
extern crate zip;

use std::io::Read;

fn main() {
    let mut res = reqwest::get("http://localhost:8000/hello.zip").unwrap();

    let mut buf: Vec<u8> = Vec::new();
    let _ = res.read_to_end(&mut buf);

    let reader = std::io::Cursor::new(buf);
    let mut zip = zip::ZipArchive::new(reader).unwrap();

    let mut file_zip = zip.by_name("hello.txt").unwrap();
    let mut file_buf: Vec<u8> = Vec::new();
    let _ = file_zip.read_to_end(&mut file_buf);

    let content = String::from_utf8(file_buf).unwrap();

    println!("{}", content);
}

Это выдаст hello world

...