我的问题的根源是我需要能够获取已下载的总字节数以显示进度条作为 cli 工具的一部分。
我正在通过 HTTP GET 请求下载文件。使用“Content-Length”http header ,我可以看到我将使用我的客户端下载的文件的总大小。我想我会做旧的“下载/总计=进度”公式。
我当前的实现可以毫无问题地获取文件并将其写入本地文件系统,因此请求和端口的设置按预期工作,我真的只需要一些指导,了解如何深入了解输入端口是什么实际上在做(事件?)我对 Racket 很陌生。
我正在使用以下库来发出 http 请求:
https://docs.racket-lang.org/http/index.html?q=http
提到了有助于实现进度条的有用程序:
https://github.com/greghendershott/http/blob/master/http/request.rkt#L505
这是我目前所拥有的:
#| Basically just for debugging/testing, receives the default input-port
#| and headers from the call/input-request procedure
(define (handle-entity in headers)
(display headers)
#| looking at the source this "read-entity/transfer-decoding-port"
#| should be useful for what I want to do
(define decoded-port (read-entity/transfer-decoding-port in headers))
#| writing the file works as expected, what I really want to do is
#| is get the download progress as I write to the output-port
(call-with-output-file "test.tar.gz"
(lambda (out)
(display (port->bytes decoded-port) out))))
(define (fetch)
(call/input-request "1.1"
"GET"
"https://example.com/test.tar.gz"
empty
handle-entity #| will handle the input port created in this procedure
#:redirects 10))
最佳答案
您可以使用 port-progress-evt
有效地等到端口被读取,你可以使用 port-next-location
检查到目前为止已经读取了多少字节。您可以在另一个线程的循环中执行此操作以异步更新进度条。例如:
(define (listen-for-progress in)
(sync (port-progress-evt in))
(unless (port-closed? in)
(define-values [line col pos] (port-next-location in))
(printf "bytes read: ~a\n" pos)
(listen-for-progress in)))
(define (read-with-progress in)
(thread (λ () (listen-for-progress in)))
#| do something with in |#)
顺便说一句,你应该使用 copy-port
而不是 port->bytes
后跟 display
,因为 copy-port
会将输入端口流式传输到输出端口,但是
port->bytes
将在开始写入输出端口之前将整个端口读入内存。
关于http - 如何在从 Racket 输入端口读取时显示 HTTP 文件下载进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50849325/