Nicolas Neuss neuss@math.uni-karlsruhe.de writes:
I want to return some data in CSV format (or also PDF format in another application). At the moment I am using something like
(let ((file "output.csv")) (with-open-file (stream file :direction :output :if-exists :supersede) (csv-output stream ...)) (handle-static-file file) (delete-file file))
However, this is clearly not good in a multiprocessing situation, and I would like to get rid of the intermediate file. Is it possible to publish the stream output directly?
If I were you, I'd start with looking at the source code of HANDLE-STATIC-FILE:
(defun handle-static-file (path &optional content-type) "A function which acts like a Hunchentoot handler for the file denoted by PATH. Send a content type header corresponding to CONTENT-TYPE or (if that is NIL) tries to determine the content type via the file's suffix." (unless (or (pathname-name path) (pathname-type path)) ;; not a file (setf (return-code) +http-bad-request+) (throw 'handler-done nil)) (unless (probe-file path) ;; does not exist (setf (return-code) +http-not-found+) (throw 'handler-done nil)) (let ((time (or (file-write-date path) (get-universal-time)))) (setf (content-type) (or content-type (mime-type path) "application/octet-stream")) (handle-if-modified-since time) (with-open-file (file path :direction :input :element-type '(unsigned-byte 8) :if-does-not-exist nil) (setf (header-out "Last-Modified") (rfc-1123-date time) (content-length) (file-length file)) (let ((out (send-headers))) (loop with buf = (make-array +buffer-length+ :element-type '(unsigned-byte 8)) for pos = (read-sequence buf file) until (zerop pos) do (write-sequence buf out :end pos) (finish-output out))))))
The trick is to send the will be transfered content to the stream returned by call to SEND-HEADERS. Also, don't forget to check the SEND-HEADERS documentation from the Hunchentoot manual:
... Returns a flexi stream to which the body of the reply can be written. Once this function has been called, further changes to *REPLY* don't have any effect. Also, automatic handling of errors (i.e. sending the corresponding status code to the browser, etc.) is turned off for this request. ...
(More is in the documentation.)
Regards.