11package clientv2
22
33import (
4+ "fmt"
45 "io"
56 "mime/multipart"
7+ "net/textproto"
8+ "strings"
69
710 "github.com/qiniu/go-sdk/v7/internal/context"
811 compatible_io "github.com/qiniu/go-sdk/v7/internal/io"
1316 key , value string
1417 }
1518 keyFilePair struct {
16- key , fileName string
17- stream compatible_io.ReadSeekCloser
19+ key , fileName , contentType string
20+ stream compatible_io.ReadSeekCloser
1821 }
1922
2023 MultipartForm struct {
@@ -29,16 +32,17 @@ type (
2932 multipartWriter * multipart.Writer
3033 form * MultipartForm
3134 r * io.PipeReader
35+ closed bool
3236 }
3337)
3438
3539func (f * MultipartForm ) SetValue (key , value string ) * MultipartForm {
36- f .values = append (f .values , keyValuePair {key : key , value : value })
40+ f .values = append (f .values , keyValuePair {key , value })
3741 return f
3842}
3943
40- func (f * MultipartForm ) SetFile (key , fileName string , stream compatible_io.ReadSeekCloser ) * MultipartForm {
41- f .files = append (f .files , keyFilePair {key : key , fileName : fileName , stream : stream })
44+ func (f * MultipartForm ) SetFile (key , fileName , contentType string , stream compatible_io.ReadSeekCloser ) * MultipartForm {
45+ f .files = append (f .files , keyFilePair {key , fileName , contentType , stream })
4246 return f
4347}
4448
@@ -67,7 +71,7 @@ func newMultipartFormReader(form *MultipartForm) *multipartFormReader {
6771 case <- ctx .Done ():
6872 return
6973 default :
70- if err := reader .createFormFile (pair .key , pair .fileName , pair .stream ); err != nil {
74+ if err := reader .createFormFile (pair .key , pair .fileName , pair .contentType , pair . stream ); err != nil {
7175 cancel (err )
7276 return
7377 }
@@ -88,6 +92,10 @@ func (r *multipartFormReader) Read(p []byte) (int, error) {
8892}
8993
9094func (r * multipartFormReader ) Close () (err error ) {
95+ if r .closed {
96+ return nil
97+ }
98+ r .closed = true
9199 r .form .cancel (io .ErrClosedPipe )
92100 err = r .r .Close ()
93101 for _ , pair := range r .form .files {
@@ -102,8 +110,11 @@ func (r *multipartFormReader) formDataContentType() string {
102110 return r .multipartWriter .FormDataContentType ()
103111}
104112
105- func (r * multipartFormReader ) createFormFile (fieldName , fileName string , stream compatible_io.ReadSeekCloser ) error {
106- if w , err := r .multipartWriter .CreateFormFile (fieldName , fileName ); err != nil {
113+ func (r * multipartFormReader ) createFormFile (fieldName , fileName , contentType string , stream compatible_io.ReadSeekCloser ) error {
114+ h := make (textproto.MIMEHeader )
115+ h .Set ("Content-Disposition" , fmt .Sprintf (`form-data; name="%s"; filename="%s"` , escapeQuotes (fieldName ), escapeQuotes (fileName )))
116+ h .Set ("Content-Type" , contentType )
117+ if w , err := r .multipartWriter .CreatePart (h ); err != nil {
107118 return err
108119 } else if _ , err := io .Copy (w , stream ); err != nil {
109120 return err
@@ -133,3 +144,9 @@ func GetMultipartFormRequestBody(info *MultipartForm) GetRequestBody {
133144 return r , nil
134145 }
135146}
147+
148+ var quoteEscaper = strings .NewReplacer ("\\ " , "\\ \\ " , `"` , "\\ \" " )
149+
150+ func escapeQuotes (s string ) string {
151+ return quoteEscaper .Replace (s )
152+ }
0 commit comments