[REBOL] Re: hook while downloading from html port
From: Gary:Jones:usap:gov at: 16-Apr-2004 12:35
From: Anton Rolls
AR> Scott, I think you are a bit negative about transfer rates. :)
AR> Surely there is a way.
....
It was one of those things were as soon as I sent my email, I, too, thought of a way
to show progress, but our satellite signals times are limited. My guess is that there
will already be 3 more ways to do it by the time this arrives!
Not unlike Anton's way in using read, I capture the actual bytes read from the return
of read-io and accumulate these in a variable. If the site provides content length,
then the patch can compare sent to expected. Unfortunately, not all servers/websites
send the content length.
At the end of the http scheme, and the variable "bytes-transferred", as in:
...
cache-size: 5
user-agent: "REBOL View 1.2.10.3.1"
bytes-transferred: 0
]
Then change the read function to (watch for line wrap):
read: func [
port "An open port spec"
data "A buffer to use for the read"
/local bytes-read
][
net-utils/net-log ["low level read of " port/state/num "bytes"]
bytes-read: read-io port/sub-port data port/state/num
bytes-transferred: bytes-transferred + bytes-read
if port/locals/headers/content-length <> none [print [to-integer (bytes-transferred /
(to-integer port/locals/headers/content-length) * 100) "percent"]]
bytes-read
]
Reading a page in which the server gives content-length will allow the calculation of
percent received. I realized that the read function needs to return the bytes, read,
hence the last line.
Expanding on the idea, I decided for fun to try to create a visual feedback method that
gives progress bar when the content-length is known, or simple accumulated bytes retrieved,
when content-length was unknown. It requires a fair amount of patching.
Starting with a fresh copy of the http scheme, one first alters the continue-post function:
continue-post: func [/tunnel] [
response-line: system/words/pick port/sub-port 1
net-utils/net-log response-line
either none? response-line [do error] [
either none? result: select either tunnel [tunnel-actions] [response-actions]
response-code: to-integer second parse response-line none [do error] [do get result]
]
if show-progress [
either port/locals/headers/content-length <> none [
progress-message/pane: layout/origin/offset [p: progress] 0x0 0x0
show progress-message
][
progress-message/pane: layout/origin/offset [t: text 200x16] 0x0 0x0
show progress-message
]
]
]
Then following the close block and build-port further down, one inserts these lines
....
]
build-port ;insert following lines
if all [block? port/state/custom post-data: find port/state/custom to-lit-word 'progress
block? post-data] [
show-progress: true
progress-message: get to-word select port/state/custom to-lit-word 'progress
]
Then one changes the close function:
close: func [port][
if show-progress [
progress-message/pane: layout/origin/offset [t: text 200x16] 0x0 0x0
show progress-message
t/text: "Done!"
show t
show-progress: none
]
system/words/close port/sub-port
bytes-transferred: 0
]
One changes the read function:
read: func [
port "An open port spec"
data "A buffer to use for the read"
/local bytes-read
][
net-utils/net-log ["low level read of " port/state/num "bytes"]
bytes-read: read-io port/sub-port data port/state/num
bytes-transferred: bytes-transferred + bytes-read
if show-progress [
either port/locals/headers/content-length <> none [
p/data: bytes-transferred / (to-integer port/locals/headers/content-length)
show p
;loop 10000000 [] ;uncomment to see fast pages load
][
t/text: bytes-transferred
show t
;loop 10000000 []
]
]
bytes-read
]
Finally, one adds variables to the end of the scheme:
.....
user-agent: "REBOL View 1.2.10.3.1"
bytes-transferred: 0
show-progress: progress-message: p: t: none
]
One uses the custom refinement to pass the reference to a VID box:
view layout [
f: field 300x24
button "Get Page" [
read/custom trim to-url f/text ['progress :my-pane]
]
my-pane: box 200x16
button "Exit" [quit]
]
When one types in a url from a website where the server gives the content-length, the
box gets a progress bar embedded, which is then updated based on the percentage of bytes
read. When the url is served from a server that does not give the content-length, then
the bytes retrieved are displayed. After completed, the progress box is converted to
text that says "Done!" I have commented out some do nothing loops in case your downloads
are too fast, and you are trying to see the changes at work.
I was just about to send this when I received the most recent set of emails, including
Max's own patch on read-net. Oh well, it still may prove useful to him or someone else
in another context and/or to take advantage of all the extra features of the http protocol.
--Scott Jones