Skip to content

Commit a93d17b

Browse files
committed
PartialRange download example cleanup
1 parent 9084c13 commit a93d17b

File tree

2 files changed

+56
-62
lines changed

2 files changed

+56
-62
lines changed

src/intro.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ community. It needs and welcomes help. For details see
222222
[ex-url-parse]: net.html#ex-url-parse
223223
[ex-url-rm-frag]: net.html#ex-url-rm-frag
224224
[ex-urlencoded]: encoding.html#ex-urlencoded
225+
[ex-progress-with-range]: net.html#ex-random-file-access
225226
[ex-random-file-access]: basics.html#ex-random-file-access
226227
[ex-regex-replace-named]: basics.html#ex-regex-replace-named
227228
[ex-csv-filter]: encoding.html#ex-csv-filter

src/net.md

Lines changed: 55 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,101 +1029,94 @@ fn run() -> Result<()> {
10291029
Uses [`reqwest::Client::head`] to get the content-length and validate if the server sets the header
10301030
[`reqwest::header::ContentRange`], required to confirm the support of partial downloads.
10311031

1032-
If supported downloads the content using [`reqwest::get`], setting the [`reqwest::header::Range`]
1033-
to do partial downloads in chunks of 100 bytes, between these writes basic progress messages.
1032+
If supported, downloads the content using [`reqwest::get`], setting the [`reqwest::header::Range`]
1033+
to do partial downloads printing basic progress messages.
1034+
in chunks of 10240 bytes
10341035

1035-
Range header, defined in [RFC7233][HTTP Range RFC7233].
1036+
Range header is defined in [RFC7233][HTTP Range RFC7233].
10361037

10371038
```rust,no_run
10381039
# #[macro_use]
10391040
# extern crate error_chain;
10401041
extern crate reqwest;
10411042
1042-
use std::io::{Read, Write};
10431043
use std::fs::File;
1044-
10451044
use reqwest::header::{ContentRange, ContentRangeSpec, Range};
1046-
1045+
use reqwest::StatusCode;
1046+
#
10471047
# error_chain! {
10481048
# foreign_links {
10491049
# Io(std::io::Error);
10501050
# Reqwest(reqwest::Error);
10511051
# }
10521052
# }
1053-
1054-
#[derive(Debug)]
1055-
struct PartialRangeIter {
1056-
start: u64,
1057-
end: u64,
1058-
buffer_size: usize,
1059-
}
1060-
1061-
impl PartialRangeIter {
1062-
pub fn new(content_range: &ContentRangeSpec, buffer_size: usize) -> Result<PartialRangeIter> {
1063-
if buffer_size == 0 {
1064-
Err("invalid buffer_size, give a value greater than zero.")?;
1065-
}
1066-
1067-
match *content_range {
1068-
ContentRangeSpec::Bytes { range: Some(range), .. } => Ok(PartialRangeIter {
1069-
start: range.0,
1070-
end: range.1,
1071-
buffer_size,
1072-
}),
1073-
_ => Err("invalid range specification")?,
1074-
}
1075-
}
1076-
}
1077-
1078-
impl Iterator for PartialRangeIter {
1079-
type Item = Range;
1080-
1081-
fn next(&mut self) -> Option<Self::Item> {
1082-
if self.start > self.end {
1083-
None
1084-
} else {
1085-
let old_start = self.start;
1086-
self.start += std::cmp::min(self.buffer_size as u64, self.end - self.start + 1);
1087-
Some(Range::bytes(old_start, self.start - 1))
1088-
}
1089-
}
1090-
}
1091-
1053+
#
1054+
# struct PartialRangeIter {
1055+
# start: u64,
1056+
# end: u64,
1057+
# buffer_size: u32,
1058+
# }
1059+
#
1060+
# impl PartialRangeIter {
1061+
# pub fn new(content_range: &ContentRangeSpec, buffer_size: u32) -> Result<Self> {
1062+
# if buffer_size == 0 {
1063+
# Err("invalid buffer_size, give a value greater than zero.")?;
1064+
# }
1065+
#
1066+
# match *content_range {
1067+
# ContentRangeSpec::Bytes { range: Some(range), .. } => Ok(PartialRangeIter {
1068+
# start: range.0,
1069+
# end: range.1,
1070+
# buffer_size,
1071+
# }),
1072+
# _ => Err("invalid range specification")?,
1073+
# }
1074+
# }
1075+
# }
1076+
#
1077+
# impl Iterator for PartialRangeIter {
1078+
# type Item = Range;
1079+
#
1080+
# fn next(&mut self) -> Option<Self::Item> {
1081+
# if self.start > self.end {
1082+
# None
1083+
# } else {
1084+
# let prev_start = self.start;
1085+
# self.start += std::cmp::min(self.buffer_size as u64, self.end - self.start + 1);
1086+
# Some(Range::bytes(prev_start, self.start - 1))
1087+
# }
1088+
# }
1089+
# }
10921090
10931091
fn run() -> Result<()> {
1094-
let client = reqwest::Client::new();
1095-
1096-
// For the purpose of this example is only a small download of 102400 bytes.
1092+
// For the purpose of this example only a small download of 102400 bytes
1093+
// with chunk size of 10240 bytes is used.
10971094
let url = "https://httpbin.org/range/102400?duration=2";
1098-
let response = client.head(url).send()?;
1095+
const CHUNK_SIZE: u32 = 10240;
10991096
1097+
let client = reqwest::Client::new();
1098+
let response = client.head(url).send()?;
11001099
let range = response.headers().get::<ContentRange>().ok_or(
11011100
"response doesn't include the expected ranges",
11021101
)?;
11031102
11041103
let mut output_file = File::create("download.bin")?;
11051104
1106-
let mut content_buffer: Vec<u8> = Vec::with_capacity(10000);
1107-
let ranges = PartialRangeIter::new(range, content_buffer.capacity())?;
1108-
11091105
println!("starting download...");
1110-
for range in ranges {
1111-
println!("range {:?}", range);
1106+
for range in PartialRangeIter::new(range, CHUNK_SIZE)? {
11121107
1108+
println!("range {:?}", range);
11131109
let mut response = client.get(url).header(range).send()?;
11141110
1115-
if !(response.status() == reqwest::StatusCode::Ok ||
1116-
response.status() == reqwest::StatusCode::PartialContent)
1117-
{
1118-
bail!("Unexpected server response: {}", response.status())
1111+
let status = response.status();
1112+
if !(status == StatusCode::Ok || status == StatusCode::PartialContent) {
1113+
bail!("Unexpected server response: {}", status)
11191114
}
11201115
1121-
response.read_to_end(&mut content_buffer)?;
1122-
output_file.write_all(&content_buffer)?;
1123-
content_buffer.clear();
1116+
std::io::copy(&mut response, &mut output_file)?;
11241117
}
11251118
1126-
println!("finished with success!");
1119+
println!("Finished with success!");
11271120
Ok(())
11281121
}
11291122
#

0 commit comments

Comments
 (0)