github.com/qiniu/go-sdk/v7@v7.27.0/sandbox/multipart.go (about)

     1  package sandbox
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"mime/multipart"
     7  	"net/textproto"
     8  	"path/filepath"
     9  	"strings"
    10  )
    11  
    12  // multipartFileWriter 封装 multipart 文件上传的 writer。
    13  type multipartFileWriter struct {
    14  	w *multipart.Writer
    15  }
    16  
    17  // newMultipartWriter 创建一个写入到 w 的 multipartFileWriter。
    18  func newMultipartWriter(w io.Writer) *multipartFileWriter {
    19  	return &multipartFileWriter{w: multipart.NewWriter(w)}
    20  }
    21  
    22  // contentType 返回 multipart 的 Content-Type 头。
    23  func (m *multipartFileWriter) contentType() string {
    24  	return m.w.FormDataContentType()
    25  }
    26  
    27  // writeFile 将文件数据写入 multipart body。
    28  func (m *multipartFileWriter) writeFile(fieldName, fileName string, data []byte) error {
    29  	part, err := m.w.CreateFormFile(fieldName, filepath.Base(fileName))
    30  	if err != nil {
    31  		return err
    32  	}
    33  	_, err = part.Write(data)
    34  	return err
    35  }
    36  
    37  // writeFileFullPath 将文件数据写入 multipart body,part filename 使用完整路径。
    38  // 用于批量上传场景,服务端从 part filename 获取文件路径。
    39  // 不使用 CreateFormFile,因为它会对 filename 执行 filepath.Base()。
    40  func (m *multipartFileWriter) writeFileFullPath(fieldName, fullPath string, data []byte) error {
    41  	h := make(textproto.MIMEHeader)
    42  	h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%s"; filename="%s"`, escapeQuotes(fieldName), escapeQuotes(fullPath)))
    43  	h.Set("Content-Type", "application/octet-stream")
    44  	part, err := m.w.CreatePart(h)
    45  	if err != nil {
    46  		return err
    47  	}
    48  	_, err = part.Write(data)
    49  	return err
    50  }
    51  
    52  var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
    53  
    54  // escapeQuotes 转义字符串中的反斜杠和双引号,用于 Content-Disposition 头部。
    55  func escapeQuotes(s string) string {
    56  	return quoteEscaper.Replace(s)
    57  }
    58  
    59  // close 关闭 multipart writer。
    60  func (m *multipartFileWriter) close() error {
    61  	return m.w.Close()
    62  }