rabbibotton / clog

CLOG - The Common Lisp Omnificent GUI
Other
1.48k stars 101 forks source link

Upload file with form wichout reloading #272

Closed ebrasca closed 1 year ago

ebrasca commented 1 year ago

Can you upload files without reloading the page?

rabbibotton commented 1 year ago

The main way this is done is by creating a hidden iframe

ebrasca commented 1 year ago

I have found that you can use Javascript instead of the iframes. https://www.hungred.com/how-to/tutorial-easiest-asynchronous-upload-file-ajax-upload/ Are iframes better? How to add javascript features like this one to clog? Thank you!

aykaramba commented 1 year ago

I would love to hear to receive what that javascript is submiting as well.

If you are interested, here is my file select and file receive/save code:

;;;;;;
;; this is the file selection form
;;;;;;

(defun form-select (obj)
  (let* (;; 1/3rd container
     (c2 (create-div c1 :content "" :class "w3-half"))
     ;; card
     (c3 (create-div c2 :content "" :class "w3-card-4 w3-animate-zoom "))
     ;; container3
     (fcontainer3 (create-div c3 :class "w3-container w3-teal w3-center"))
     (tmp        (create-section fcontainer3 :h2 :content "File Upload Form"))
     ;; container4
     (fcontainer4 (create-div c3 :class "w3-center"))
     (tmp        (create-br fcontainer4))
     ;; form
     (form3      (create-form fcontainer4 :method :post
                         :encoding "multipart/form-data"
                         :action "/galleri-submit"
                         ))
     (finput3     (create-form-element form3 :file :name "filename"))
     (fsubmit3    (create-form-element form3 :submit))
     (tmp         (create-br fcontainer4))
     (tmp         (create-hr fcontainer4)))

    (declare (ignore tmp) (ignore finput3) (ignore fsubmit3) (ignore link-01))

    (set-on-click link-01 
          (lambda (obj)
            (let* (;; row
               (c1 (create-div obj :content ""  :class "w3-row-padding w3-margin-top"))
               ;; 1/3rd container
               (c2 (create-div c1 :content "" :class "w3-third"))
               ;; the card to stuff the image into
               (c3 (create-div c2 :content "" :class "w3-card-4 "))
               ;; the image inside the card
               (c4 (create-img c3 :url-src "http://127.0.0.1:8080/img/w01.png" :style "width:100%"))
               ;; image label
               (c5 (create-div c3 :content "Gallery" :class "w3-container w3-padding "))))))))

;;;;;;
;; this receives the data, saves it to a folder and inserts path to
;;;;;;

(defun form-submit (obj)
      (create-div obj :content "boo" :class "w3-red" )

      (let* ((params (form-multipart-data obj)))

    (destructuring-bind (stream fname content-type)
        (form-data-item params "filename")
      (with-open-file (os
               (make-pathname
                :directory '(:relative "/www/upload")
                :name fname)
               :direction :output
               :if-exists :rename
               :element-type '(unsigned-byte 8))
        (let ((s (flexi-streams:make-flexi-stream stream)))
          (loop for byte = (read-byte s nil)
            while byte
            do (write-byte byte os))))

      (create-div obj :content params)
      (create-div obj :content (form-data-item params "filename"))
      (create-div obj :content content-type)
      (create-div obj :content fname)
      (create-div obj :content (make-pathname
                    :directory '(:relative "/www/upload")
                    :name fname))
      (create-div obj :content (make-pathname
                    :directory '(:relative "/www/upload")))

      ;; db stuff
      (dbi:do-sql
        *sql-connection*
        (sql-insert* "images2" `(:folder "upload"
                     :name ,(princ fname)
                     :type ,(princ content-type)
                     :date (,*sqlite-timestamp*))))

      (create-div obj :content "<a href=\"http://127.0.0.1:8080/galleri\"> GO BACK </a>"))
    (delete-multipart-data obj)))