在 Squeak 中,一旦块到达,就将大 HTTP 响应的块写入磁盘
Writing chunks of a large HTTP response to disk as soon as chunks arrive, in Squeak
我正在尝试从 squeak 下载文件到磁盘。
我的方法适用于小型 text/html 文件,
但由于缺乏缓冲,
对于大型二进制文件来说非常慢
https://mirror.racket-lang.org/installers/6.12/racket-6.12-x86_64-win32.exe。
此外,完成后,文件要大得多 (113 MB)
比下载页面上显示的 (75MB)。
我的代码如下所示:
download: anURL
"download a file over HTTP and save it to disk under a name extracted from url."
| ios name |
name := ((anURL findTokens: '/') removeLast findTokens: '?') removeFirst.
ios := FileStream oldFileNamed: name.
ios nextPutAll: ((HTTPClient httpGetDocument: anURL) content).
ios close.
Transcript show: 'done'; cr.
我已经尝试 [bytes = stream next bufSize. bytes printTo: ios]
使用 [stream atEnd] whileFalse:
循环在 HTTP 响应的 contentStream
中使用固定大小的块,但这会使输出文件出现乱码,每个块周围都带有单引号,而且还有额外的块之后的内容,看起来像流中的所有字符,每个字符都用引号引起来。
如何实现将 HTTP 响应缓冲写入磁盘文件?
另外,有没有办法在显示下载进度的同时发出吱吱声?
正如 Leandro 已经写的那样,问题出在 #binary
。
你的代码几乎是正确的,我冒昧地 运行 它 - 现在它正确地下载了整个文件:
| ios name anURL |
anURL := ' https://mirror.racket-lang.org/installers/6.12/racket-6.12-x86_64-win32.exe'.
name := ((anURL findTokens: '/') removeLast findTokens: '?') removeFirst.
ios := FileStream newFileNamed: 'C:\Users\user\Downloads\_squeak\', name.
ios binary.
ios nextPutAll: ((HTTPClient httpGetDocument: anURL) content).
ios close.
Transcript show: 'done'; cr.
至于卡顿,我认为问题出在您下载时整个环境的一个线程。这意味着在您下载整个文件之前,您将无法使用 Squeak。
刚刚在 Pharo 中测试(安装更简单),下面的代码可以正常工作:
ZnClient new
url: 'https://mirror.racket-lang.org/installers/6.12/racket-6.12-x86_64-win32.exe';
downloadTo: 'C:\Users\user\Downloads\_squeak'.
WebResponse
class,在构建响应内容时,会创建一个足够大的缓冲区来容纳整个响应,即使是巨大的响应!我认为这是由于 WebMessage>>#getContentWithProgress:
.
中的代码造成的
我试图将数据从 WebResponse
的输入 SocketStream
直接复制到输出 FileStream
。
我只好subclassWebClient
和WebResponse
,写了两个方法。
现在,以下代码可以按要求工作。
| client link |
client := PkWebClient new.
link := 'http://localhost:8000/racket-6.12-x86_64-linux.sh'.
client download: link toFile: '/home/yo/test'.
我已逐块验证下载文件的更新和完整性。
我在下面包含源代码。方法 streamContentDirectToFile: aFilePathString
是一种以不同方式做事并解决问题的方法。
WebClient subclass: #PkWebClient
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'PK'!
!PkWebClient commentStamp: 'pk 3/28/2018 20:16' prior: 0!
Trying to download http directly to file.!
!PkWebClient methodsFor: 'as yet unclassified' stamp: 'pk 3/29/2018 13:29'!
download: urlString toFile: aFilePathString
"Try to download large files sensibly"
| res |
res := self httpGet: urlString.
res := PkWebResponse new copySameFrom: res.
res streamContentDirectToFile: aFilePathString! !
WebResponse subclass: #PkWebResponse
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'PK'!
!PkWebResponse commentStamp: 'pk 3/28/2018 20:49' prior: 0!
To make getContentwithProgress better.!
]style[(38)f1!
!PkWebResponse methodsFor: 'as yet unclassified' stamp: 'pk 3/29/2018 13:20'!
streamContentDirectToFile: aFilePathString
"stream response's content directly to file."
| buffer ostream |
stream binary.
buffer := ByteArray new: 4096.
ostream := FileStream oldFileNamed: aFilePathString.
ostream binary.
[stream atEnd]
whileFalse: [buffer := stream nextInBuffer: 4096.
stream receiveAvailableData.
ostream nextPutAll: buffer].
stream close.
ostream close! !
我正在尝试从 squeak 下载文件到磁盘。 我的方法适用于小型 text/html 文件, 但由于缺乏缓冲, 对于大型二进制文件来说非常慢 https://mirror.racket-lang.org/installers/6.12/racket-6.12-x86_64-win32.exe。 此外,完成后,文件要大得多 (113 MB) 比下载页面上显示的 (75MB)。
我的代码如下所示:
download: anURL
"download a file over HTTP and save it to disk under a name extracted from url."
| ios name |
name := ((anURL findTokens: '/') removeLast findTokens: '?') removeFirst.
ios := FileStream oldFileNamed: name.
ios nextPutAll: ((HTTPClient httpGetDocument: anURL) content).
ios close.
Transcript show: 'done'; cr.
我已经尝试 [bytes = stream next bufSize. bytes printTo: ios]
使用 [stream atEnd] whileFalse:
循环在 HTTP 响应的 contentStream
中使用固定大小的块,但这会使输出文件出现乱码,每个块周围都带有单引号,而且还有额外的块之后的内容,看起来像流中的所有字符,每个字符都用引号引起来。
如何实现将 HTTP 响应缓冲写入磁盘文件? 另外,有没有办法在显示下载进度的同时发出吱吱声?
正如 Leandro 已经写的那样,问题出在 #binary
。
你的代码几乎是正确的,我冒昧地 运行 它 - 现在它正确地下载了整个文件:
| ios name anURL |
anURL := ' https://mirror.racket-lang.org/installers/6.12/racket-6.12-x86_64-win32.exe'.
name := ((anURL findTokens: '/') removeLast findTokens: '?') removeFirst.
ios := FileStream newFileNamed: 'C:\Users\user\Downloads\_squeak\', name.
ios binary.
ios nextPutAll: ((HTTPClient httpGetDocument: anURL) content).
ios close.
Transcript show: 'done'; cr.
至于卡顿,我认为问题出在您下载时整个环境的一个线程。这意味着在您下载整个文件之前,您将无法使用 Squeak。
刚刚在 Pharo 中测试(安装更简单),下面的代码可以正常工作:
ZnClient new
url: 'https://mirror.racket-lang.org/installers/6.12/racket-6.12-x86_64-win32.exe';
downloadTo: 'C:\Users\user\Downloads\_squeak'.
WebResponse
class,在构建响应内容时,会创建一个足够大的缓冲区来容纳整个响应,即使是巨大的响应!我认为这是由于 WebMessage>>#getContentWithProgress:
.
我试图将数据从 WebResponse
的输入 SocketStream
直接复制到输出 FileStream
。
我只好subclassWebClient
和WebResponse
,写了两个方法。
现在,以下代码可以按要求工作。
| client link |
client := PkWebClient new.
link := 'http://localhost:8000/racket-6.12-x86_64-linux.sh'.
client download: link toFile: '/home/yo/test'.
我已逐块验证下载文件的更新和完整性。
我在下面包含源代码。方法 streamContentDirectToFile: aFilePathString
是一种以不同方式做事并解决问题的方法。
WebClient subclass: #PkWebClient
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'PK'!
!PkWebClient commentStamp: 'pk 3/28/2018 20:16' prior: 0!
Trying to download http directly to file.!
!PkWebClient methodsFor: 'as yet unclassified' stamp: 'pk 3/29/2018 13:29'!
download: urlString toFile: aFilePathString
"Try to download large files sensibly"
| res |
res := self httpGet: urlString.
res := PkWebResponse new copySameFrom: res.
res streamContentDirectToFile: aFilePathString! !
WebResponse subclass: #PkWebResponse
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'PK'!
!PkWebResponse commentStamp: 'pk 3/28/2018 20:49' prior: 0!
To make getContentwithProgress better.!
]style[(38)f1!
!PkWebResponse methodsFor: 'as yet unclassified' stamp: 'pk 3/29/2018 13:20'!
streamContentDirectToFile: aFilePathString
"stream response's content directly to file."
| buffer ostream |
stream binary.
buffer := ByteArray new: 4096.
ostream := FileStream oldFileNamed: aFilePathString.
ostream binary.
[stream atEnd]
whileFalse: [buffer := stream nextInBuffer: 4096.
stream receiveAvailableData.
ostream nextPutAll: buffer].
stream close.
ostream close! !