package multipart

import "mime/multipart"

Package multipart 实现 MIME 多部分解析,如 RFC 2046 所定义。

该实现足以处理 HTTP(RFC 2388)和流行浏览器生成的多部分主体。

限制

为防止恶意输入,此包对所处理的 MIME 数据大小设置了限制。

Reader.NextPartReader.NextRawPart 将每个部分的标题数限制为 10000, Reader.ReadForm 将所有 FileHeader 中的标题总数限制为 10000。 这些限制可通过 GODEBUG=multipartmaxheaders=<值> 设置进行调整。

Reader.ReadForm 进一步将表单中的部分数限制为 1000。 此限制可通过 GODEBUG=multipartmaxparts=<值> 设置进行调整。

Index

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 解析此类头部。

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)
		}
	}

}

Output:

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 然后写入给定的值。