/src/upload.lisp

http://github.com/mtravers/wuwei · Lisp · 48 lines · 36 code · 7 blank · 5 comment · 2 complexity · d02c2db6d43f6146bcbe9693e3e79c39 MD5 · raw file

  1. (in-package :wu)
  2. (export '(parse-upload-form))
  3. ;;; Call this to parse a multipart form.
  4. ;;; Returns a list of ((<field> <value>)..., where <value> will be a pathname for the file.
  5. ;;; Not thoroughly tested, this is a very annoying piece of the web protocol
  6. (defun parse-upload-form (req &key (pathname-maker
  7. #'(lambda (name) (make-pathname :defaults (pathname "/tmp/") :name (string+ (string *session*) "_" name)))
  8. ))
  9. (do ((result nil))
  10. (())
  11. (multiple-value-bind (part-type field filename content-type)
  12. (parse-multipart-header (get-multipart-header req))
  13. (declare (ignorable content-type))
  14. ; (format t "~%Multipart part-type=~s name=~s filename=~s content-type=~s~%" part-type field filename content-type)
  15. (case part-type
  16. (:eof
  17. (return result))
  18. (:file
  19. (let ((pathname (funcall pathname-maker filename))
  20. (element-type '(unsigned-byte 8)))
  21. (with-open-file (s pathname :direction :output :if-exists :supersede :element-type element-type)
  22. (slurp-part req :stream s :element-type element-type))
  23. (push (list field pathname) result)))
  24. (:nofile
  25. (push (list field nil) result))
  26. (:data
  27. (push (list field (slurp-part req))
  28. result))
  29. (t (warn "Unknown part type ~A" part-type)
  30. (slurp-part req))))))
  31. (defparameter *buffer-size* (* 4 1024))
  32. (defun slurp-part (req &key stream (element-type '(unsigned-byte 8)))
  33. (loop with buffer = (make-array *buffer-size* :element-type element-type)
  34. for n = (get-multipart-sequence req buffer)
  35. with len = 0
  36. ;; +++ will be wrong if there are multiple buffers, but that's unlikely for a non-file
  37. finally (return (values (unless stream (vector->string buffer len)) len))
  38. while n do
  39. (incf len n)
  40. (if stream
  41. (write-sequence buffer stream :end n))))