我正在尝试下载并保存 PDF,但在写入时失败并出现 EOF 错误。 这样做的正确方法是什么?
(with-open-file (file "/home/*/test.pdf"
:direction :io
:if-does-not-exist :create
:if-exists :supersede
:element-type '(unsigned-byte 8))
(let ((input (drakma:http-request "http://www.fractalconcept.com/ex.pdf"
:want-stream t)))
(awhile (read-byte input)
(write-byte it file))
(close input)))
解决办法是我忘了使用
read-byte
的两个可选参数。
正确的方法是将
eof-error-p
和 eof-value
设置为 nil
:
(with-open-file (file "/home/*/test.pdf"
:direction :output
:if-does-not-exist :create
:if-exists :supersede
:element-type '(unsigned-byte 8))
(let ((input (drakma:http-request "http://www.fractalconcept.com/ex.pdf"
:want-stream t)))
(awhile (read-byte input nil nil)
(write-byte it file))
(close input)))
(ql:quickload "trivial-download")
(trivial-download:download URL FILE)
;几乎完全按照您的代码执行的操作,但以更大的块形式显示,并且可以显示进度条。
; QuickLisp 可以在 http://QuickLisp.org 找到。
AWHILE 可在 ARNESI 包中找到。
在撰写本文时,该答案不适用于 HTTPS URL。读取到 EOF 的流会导致
cl+ssl
意外关闭 SSL 流。还有一些更复杂的事情发生,请参阅 https://github.com/edicl/drakma/issues/138 了解更多信息。但是,我从 https://github.com/cl-plus-ssl/cl-plus-ssl/issues/166#issuecomment-1742175637 窃取的临时解决方法应该可以解决下载文件时的 cl+ssl
相关错误通过 HTTPS 使用 :want-stream t
。
(defun download-file (from-url to-file)
(with-open-file (stream to-file :direction :output
:if-exists :overwrite
:if-does-not-exist :create
:element-type '(unsigned-byte 8))
(multiple-value-bind (input status-code response-headers)
(drakma:http-request from-url :want-stream t :force-binary t)
(unless (= 200 status-code)
(error "Something wrong with the status code: ~s" status-code))
(dotimes (x (parse-integer (cdr (assoc :content-length response-headers))))
(write-byte (read-byte input nil nil) stream))
(close input))))