package multipart
import "mime/multipart"
Package multipart 实现 MIME 多部分解析,如 RFC 2046 所定义。
该实现足以处理 HTTP(RFC 2388)和流行浏览器生成的多部分主体。
限制
为防止恶意输入,此包对所处理的 MIME 数据大小设置了限制。
Reader.NextPart 和 Reader.NextRawPart 将每个部分的标题数限制为 10000, Reader.ReadForm 将所有 FileHeader 中的标题总数限制为 10000。 这些限制可通过 GODEBUG=multipartmaxheaders=<值> 设置进行调整。
Reader.ReadForm 进一步将表单中的部分数限制为 1000。 此限制可通过 GODEBUG=multipartmaxparts=<值> 设置进行调整。
Index
- Variables
- func FileContentDisposition(fieldname, filename string) string
- type File
- type FileHeader
- type Form
- type Part
- type Reader
-
type Writer
- func NewWriter(w io.Writer) *Writer
- func (w *Writer) Boundary() string
- func (w *Writer) Close() error
- func (w *Writer) CreateFormField(fieldname string) (io.Writer, error)
- func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error)
- func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, error)
- func (w *Writer) FormDataContentType() string
- func (w *Writer) SetBoundary(boundary string) error
- func (w *Writer) WriteField(fieldname, value string) error
Examples
Variables
var ErrMessageTooLarge = errors.New("multipart: message too large")
ErrMessageTooLarge 在消息表单数据太大而无法处理时由 ReadForm 返回。
Functions
func FileContentDisposition
func FileContentDisposition(fieldname, filename string) string
FileContentDisposition 返回具有给定字段名和文件名的 Content-Disposition 头部的值。
Types
type File
type File interface { io.Reader io.ReaderAt io.Seeker io.Closer }
File 是访问多部分消息文件部分的接口。 其内容可能存储在内存或磁盘上。 若存储在磁盘上,File 的底层具体类型将为 *os.File。
type FileHeader
type FileHeader struct { Filename string Header textproto.MIMEHeader Size int64 // contains filtered or unexported fields }
FileHeader 描述多部分请求的文件部分。
func (*FileHeader) Open
func (fh *FileHeader) Open() (File, error)
Open 打开并返回与 FileHeader 关联的文件。
type Form
type Form struct { Value map[string][]string File map[string][]*FileHeader }
Form 是已解析的多部分表单。 其文件部分存储在内存或磁盘上,可通过 *FileHeader 的 Open 方法访问。 其值部分存储为字符串。 两者均以字段名作为键。
func (*Form) RemoveAll
func (f *Form) RemoveAll() error
RemoveAll 删除与 Form 关联的所有临时文件。
type Part
type Part struct { // 部分的正文标题(若有),其键以与 Go http.Request 标题相同的方式规范化。 // 例如,"foo-bar" 会变为大小写 "Foo-Bar"。 Header textproto.MIMEHeader // contains filtered or unexported fields }
Part 代表多部分主体中的单个部分。
func (*Part) Close
func (p *Part) Close() error
func (*Part) FileName
func (p *Part) FileName() string
FileName 返回 Part 的 Content-Disposition 头部中的 filename 参数。 若非空,在返回前会通过 filepath.Base(取决于平台)处理。
func (*Part) FormName
func (p *Part) FormName() string
FormName 若 p 的 Content-Disposition 为 "form-data" 类型则返回 name 参数。 否则返回空字符串。
func (*Part) Read
func (p *Part) Read(d []byte) (n int, err error)
Read 读取一个部分的主体,在其标题之后、下一个部分开始之前(若有)。
type Reader
type Reader struct { // contains filtered or unexported fields }
Reader 是 MIME 多部分主体的迭代器。 Reader 的底层解析器根据需要消费其输入。不支持寻址。
func NewReader
func NewReader(r io.Reader, boundary string) *Reader
NewReader 创建一个新的 multipart Reader,从 r 读取,使用给定的 MIME 边界。
边界通常从消息的 "Content-Type" 头部的 "boundary" 参数获取。
使用 mime.ParseMediaType 解析此类头部。
Output:Example
package main
import (
"fmt"
"io"
"log"
"mime"
"mime/multipart"
"net/mail"
"strings"
)
func main() {
msg := &mail.Message{
Header: map[string][]string{
"Content-Type": {"multipart/mixed; boundary=foo"},
},
Body: strings.NewReader(
"--foo\r\nFoo: one\r\n\r\nA section\r\n" +
"--foo\r\nFoo: two\r\n\r\nAnd another\r\n" +
"--foo--\r\n"),
}
mediaType, params, err := mime.ParseMediaType(msg.Header.Get("Content-Type"))
if err != nil {
log.Fatal(err)
}
if strings.HasPrefix(mediaType, "multipart/") {
mr := multipart.NewReader(msg.Body, params["boundary"])
for {
p, err := mr.NextPart()
if err == io.EOF {
return
}
if err != nil {
log.Fatal(err)
}
slurp, err := io.ReadAll(p)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Part %q: %q\n", p.Header.Get("Foo"), slurp)
}
}
}
Part "one": "A section"
Part "two": "And another"
func (*Reader) NextPart
func (r *Reader) NextPart() (*Part, error)
NextPart 返回多部分中的下一个部分或一个错误。 当没有更多部分时,返回错误 io.EOF。
作为一个特例,若 "Content-Transfer-Encoding" 头部具有 "quoted-printable" 值, 该头部会被隐藏,正文在 Read 调用期间会被透明解码。
func (*Reader) NextRawPart
func (r *Reader) NextRawPart() (*Part, error)
NextRawPart 返回多部分中的下一个部分或一个错误。 当没有更多部分时,返回错误 io.EOF。
与 Reader.NextPart 不同,它对 "Content-Transfer-Encoding: quoted-printable" 没有特殊处理。
func (*Reader) ReadForm
func (r *Reader) ReadForm(maxMemory int64) (*Form, error)
ReadForm 解析整个多部分消息,其部分具有 "form-data" 的 Content-Disposition。 它将最多 maxMemory 字节 + 10MB(为非文件部分保留)存储在内存中。 无法存储在内存中的文件部分将存储在磁盘上的临时文件中。 若所有非文件部分都无法存储在内存中,则返回 ErrMessageTooLarge。
type Writer
type Writer struct { // contains filtered or unexported fields }
Writer 生成多部分消息。
func NewWriter
func NewWriter(w io.Writer) *Writer
NewWriter 返回一个新的 multipart Writer,带有随机边界,写入到 w。
func (*Writer) Boundary
func (w *Writer) Boundary() string
Boundary 返回 Writer 的边界。
func (*Writer) Close
func (w *Writer) Close() error
Close 完成多部分消息并将尾部边界结束行写入输出。
func (*Writer) CreateFormField
func (w *Writer) CreateFormField(fieldname string) (io.Writer, error)
CreateFormField 使用给定字段名调用 Writer.CreatePart 创建标题。
func (*Writer) CreateFormFile
func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error)
CreateFormFile 是 Writer.CreatePart 的便捷包装。它使用提供的字段名和文件名创建一个新的 form-data 标题。
func (*Writer) CreatePart
func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, error)
CreatePart 使用提供的标题创建一个新的多部分节。 部分的正文应写入返回的 Writer。调用 CreatePart 后,任何先前的部分可能无法再写入。
func (*Writer) FormDataContentType
func (w *Writer) FormDataContentType() string
FormDataContentType 返回带有此 Writer 边界的 HTTP multipart/form-data 的 Content-Type。
func (*Writer) SetBoundary
func (w *Writer) SetBoundary(boundary string) error
SetBoundary 用显式值覆盖 Writer 默认随机生成的边界分隔符。
SetBoundary 必须在创建任何部分之前调用,只能包含某些 ASCII 字符, 且必须非空且最多 70 字节长。
func (*Writer) WriteField
func (w *Writer) WriteField(fieldname, value string) error
WriteField 调用 Writer.CreateFormField 然后写入给定的值。