2017-01-03 5 views
3

Я хочу загрузить большие файлы (500 МБ) с гипер, и иметь возможность возобновить, если загрузка не удалась.Как загрузить большой файл с гипер и резюме по ошибке?

Есть ли способ с помощью функции hyper запускать некоторую функцию для каждого блока данных? Метод send() возвращает Result<Response>, но я не могу найти какие-либо методы на Response, которые возвращают итератор за куски. В идеале я бы в состоянии сделать что-то вроде:

client.get(&url.to_string()) 
    .send() 
    .map(|mut res| { 
     let mut chunk = String::new(); 
     // write this chunk to disk 
    }); 

Возможно ли это, или map вызывается только один раз гипер- скачал весь файл?

+0

'read' сам по себе, не так ли? Вы можете читать N байтов за раз. Я не уверен, что это соотносится с точно загруженными N байтами или если это просто буферизованное чтение. Но это не имеет большого значения, если вы правильно сохраните данные. – Kroltan

ответ

3

Есть ли способ, с помощью которого можно запускать некоторую функцию для каждого блока данных?

Hyper's Response осуществляет Read. Это означает, что Response является потоком, и вы можете читать произвольные фрагменты данных, как обычно, с потоком.

Для чего это стоит, вот фрагмент кода, который я использую для загрузки больших файлов из ICECat. Я использую интерфейс Read, чтобы отобразить процесс загрузки в терминале.

Переменная response здесь является примером Hyper's Response.

{ 
    let mut file = try_s!(fs::File::create(&tmp_path)); 
    let mut deflate = try_s!(GzDecoder::new(response)); 

    let mut buf = [0; 128 * 1024]; 
    let mut written = 0; 
    loop { 
     status_line! ("icecat_fetch] " (url) ": " (written/1024/1024) " MiB."); 
     let len = match deflate.read(&mut buf) { 
      Ok(0) => break, // EOF. 
      Ok(len) => len, 
      Err(ref err) if err.kind() == io::ErrorKind::Interrupted => continue, 
      Err(err) => return ERR!("{}: Download failed: {}", url, err), 
     }; 
     try_s!(file.write_all(&buf[..len])); 
     written += len; 
    } 
} 

try_s!(fs::rename(tmp_path, target_path)); 
status_line_clear(); 

Я хочу, чтобы загрузить большие файлы (500MB) с гипер, и быть в состоянии возобновить, если загрузка не выполняется.

Обычно это осуществляется с заголовком HTTP «Range» (см. RFC 7233).

Не каждый сервер поддерживает заголовок «Range». Я видел много серверов с настраиваемым стеке HTTP и без надлежащей поддержки «Range», или с отключенным заголовком «Range» по какой-то причине. Таким образом, пропуск Hyper's Response может быть необходимым резервом.

Но если вы хотите сэкономить время и трафик, то основным средством возобновления остановки загрузки должно быть использование заголовка «Range».

 Смежные вопросы

  • Нет связанных вопросов^_^