HTTP POST 提交数据之 Content-Type: multipart/form-data

4 篇文章 0 订阅

Content-Type: multiple/form-data 可以用来一次性提交较为复杂的数据结构,比如常规表单,多个文件等。

通过 boundary 定义内容分割标志和内容长度行 来综合控制包体的内容划分。

定义一般为:

POST RELATIVE_URL  HTTP/1.1

HOST: host-port

Content-length:content-length

Content-Type:multiple/form-data; boundary=i_im_boundary

Cookie:cookies

\r\n

--i_im_boundary 内容块开始

content-disposition: form-data; name="name"; 

\r\n

\r\n

content-text

\r\n

--i_im_boundary 内容块开始

content-disposition: form-data; name="name"; filename="file name.ext"

content-type: image/png

\r\n

\r\n

file-bytes

\r\n

--i_im_boundary--内容定义结束

CLISP 实现 核心代码:

(defun vector-append-vector-or-list (dst-vector src-vector-or-list)
(map 'vector (lambda (x) (vector-push-extend x dst-vector)) src-vector-or-list)
dst-vector)
(defun http-post-form-data-header (boundary)
(string2bytes 
(with-output-to-string (out)
(format out "Content-Type: multipart/form-data; boundary=~a" boundary)
(format out "~a~a" #\return #\newline)
(format out "~a~a" #\return #\newline))))
(defun http-post-form-data-text (boundary name text)
(string2bytes (with-output-to-string (out)
(format out "--~a" boundary)
(format out "~a~a" #\return #\newline)
(format out "content-disposition: form-data; name=~s" name)
(format out "~a~a" #\return #\newline)
(format out "~a~a" #\return #\newline)
(format out text)
(format out "~a~a" #\return #\newline))))


(defun http-post-form-data-file (boundary name filepath fileName content-type)
(let ((vtmp (make-array 4096 :fill-pointer 0 :adjustable t)))
(vector-append-vector-or-list 
vtmp 
(string2bytes (with-output-to-string (out)
(format out "--~a" boundary)
(format out "~a~a" #\return #\newline)
(format out "content-disposition: form-data; name=~s; filename=~s" name fileName)
(format out "~a~a" #\return #\newline)
(format out "content-type: ~a" content-type)
(format out "~a~a" #\return #\newline)
(format out "~a~a" #\return #\newline)
)))
(vector-append-vector-or-list vtmp (read-file-bytes filepath))

(vector-append-vector-or-list vtmp (list 13 10))

vtmp))


(defun read-file-bytes (file)
(with-open-file (in file :direction :input :element-type '(unsigned-byte 8))
      (loop for x = (read-byte in nil) 
while x collect x)))
;;;; multipart/form-data post数据
;HttpRequest resp = Request;
;            NameValueCollection nvList = resp.Form;
;            foreach(string file in Request.Files)
;            {
;                HttpPostedFile pfile = Request.Files[file];
;                using(System.IO.FileStream fs = new System.IO.FileStream("d:\\datatest\\"+pfile.FileName,System.IO.FileMode.OpenOrCreate))
;                {
;                   byte[] buf = new byte[4096];
;                   int len;
;
;                   fs.SetLength(0);
;
;                    while((len= pfile.InputStream.Read(buf, 0, buf.Length)) > 0)
;                    {
;                        fs.Write(buf, 0, len);
;                    }
;                }
;            }
(defun http-post2 (url)
 (let ((host nil)(rel-url nil))
  (let* ((s (+ 3 (search "://" url)))
      (e (search "/" url :start2 s)))


   (setf  host (subseq url s e)
     rel-url (subseq url e)))


  (cli-init)
  
  (let (vtmp 
(len 0) 
(boundary "AAAAA") 
(vbuf (make-array 4096 :fill-pointer 0 :adjustable t)))

(vector-append-vector-or-list vbuf (http-post-form-data-header boundary))
    
(setf vtmp (http-post-form-data-text boundary "text1" "abcd"))
(vector-append-vector-or-list vbuf vtmp)
(incf len (length vtmp))

(setf vtmp (http-post-form-data-text boundary "text2" "这是汉字部分"));
(vector-append-vector-or-list vbuf vtmp)
(incf len (length vtmp))

(setf vtmp (http-post-form-data-file boundary "file1" "e:\\aa.png" "mytest1.png" "image/png"))
(vector-append-vector-or-list vbuf vtmp)
(incf len (length vtmp))

(setf vtmp (http-post-form-data-file boundary "file2" "e:\\aa.png" "mytest2.png" "image/png"))
(vector-append-vector-or-list vbuf vtmp)
(incf len (length vtmp))

(setf vtmp (http-post-form-data-file boundary "file3" "e:\\ChromeSetup.exe" "ch.exe" "application/octer-stream"))
(vector-append-vector-or-list vbuf vtmp)
(incf len (length vtmp))

(setf vtmp (string2bytes (format nil "--~a--" boundary)))
(vector-append-vector-or-list vbuf vtmp)
(incf len (length vtmp))
    
    (http-write (format nil "POST ~a HTTP/1.1" rel-url))
    (http-write (format nil "Host: ~a" host))
    (http-write (format nil "Content-Length: ~a"  len))

(http-write-bytes vbuf))
  
  
  (when *conn*
   (http-stream-mode nil)
   (let* ((tmp-list (loop for x = (http-read-line) 
while (and x (plusp (length x)))
collect x))
   (content-length (get-content-length tmp-list)))
   
   (http-stream-mode t)
   
   ;读取返回内容
   (decode-bytes 
(loop for i from 0 to (1- content-length) for x = (http-read-byte) while x collect x)
*html-charset*)))))

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值