Involved Source Filesformdata.go
Package multipart implements MIME multipart parsing, as defined in RFC
2046.
The implementation is sufficient for HTTP (RFC 2388) and the multipart
bodies generated by popular browsers.
writer.go
Form is a parsed multipart form.
Its File parts are stored either in memory or on disk,
and are accessible via the *FileHeader's Open method.
Its Value parts are stored as strings.
Both are keyed by field name.
Filemap[string][]*FileHeaderValuemap[string][]string
RemoveAll removes any temporary files associated with a Form.
func (*Reader).ReadForm(maxMemory int64) (*Form, error)
func (*Reader).readForm(maxMemory int64) (_ *Form, err error)
func net/http.cloneMultipartForm(f *Form) *Form
func net/http.cloneMultipartForm(f *Form) *Form
var net/http.multipartByReader *Form
A Part represents a single part in a multipart body.
The headers of the body, if any, with the keys canonicalized
in the same fashion that the Go http.Request headers are.
For example, "foo-bar" changes case to "Foo-Bar"
dispositionstringdispositionParamsmap[string]string
// error to return when n == 0
mr*Reader
// known data bytes waiting in mr.bufReader
r is either a reader directly reading from mr, or it's a
wrapper around such a reader, decoding the
Content-Transfer-Encoding
// read error observed from mr.bufReader
// total data bytes read already
(*T) Close() error
FileName returns the filename parameter of the Part's
Content-Disposition header.
FormName returns the name parameter if p has a Content-Disposition
of type "form-data". Otherwise it returns the empty string.
Read reads the body of a part, after its headers and before the
next part (if any) begins.
(*T) parseContentDisposition()(*T) populateHeaders() error
*T : io.Closer
*T : io.ReadCloser
*T : io.Reader
func (*Reader).NextPart() (*Part, error)
func (*Reader).NextRawPart() (*Part, error)
func newPart(mr *Reader, rawPart bool) (*Part, error)
func (*Reader).nextPart(rawPart bool) (*Part, error)
Reader is an iterator over parts in a MIME multipart body.
Reader's underlying parser consumes its input as needed. Seeking
isn't supported.
bufReader*bufio.ReadercurrentPart*Part
// "--boundary"
// "--boundary--"
// "\r\n" or "\n" (set after seeing first boundary line)
// nl + "--boundary"
partsReadint
NextPart returns the next part in the multipart or an error.
When there are no more parts, the error io.EOF is returned.
As a special case, if the "Content-Transfer-Encoding" header
has a value of "quoted-printable", that header is instead
hidden and the body is transparently decoded during Read calls.
NextRawPart returns the next part in the multipart or an error.
When there are no more parts, the error io.EOF is returned.
Unlike NextPart, it does not have special handling for
"Content-Transfer-Encoding: quoted-printable".
ReadForm parses an entire multipart message whose parts have
a Content-Disposition of "form-data".
It stores up to maxMemory bytes + 10MB (reserved for non-file parts)
in memory. File parts which can't be stored in memory will be stored on
disk in temporary files.
It returns ErrMessageTooLarge if all non-file parts can't be stored in
memory.
(*T) isBoundaryDelimiterLine(line []byte) (ret bool)
isFinalBoundary reports whether line is the final boundary line
indicating that all parts are over.
It matches `^--boundary--[ \t]*(\r\n)?$`
(*T) nextPart(rawPart bool) (*Part, error)(*T) readForm(maxMemory int64) (_ *Form, err error)
func NewReader(r io.Reader, boundary string) *Reader
func net/http.(*Request).MultipartReader() (*Reader, error)
func net/http.(*Request).multipartReader(allowMixed bool) (*Reader, error)
func newPart(mr *Reader, rawPart bool) (*Part, error)
A Writer generates multipart messages.
boundarystringlastpart*partwio.Writer
Boundary returns the Writer's boundary.
Close finishes the multipart message and writes the trailing
boundary end line to the output.
CreateFormField calls CreatePart with a header using the
given field name.
CreateFormFile is a convenience wrapper around CreatePart. It creates
a new form-data header with the provided field name and file name.
CreatePart creates a new multipart section with the provided
header. The body of the part should be written to the returned
Writer. After calling CreatePart, any previous part may no longer
be written to.
FormDataContentType returns the Content-Type for an HTTP
multipart/form-data with this Writer's Boundary.
SetBoundary overrides the Writer's default randomly-generated
boundary separator with an explicit value.
SetBoundary must be called before any parts are created, may only
contain certain ASCII characters, and must be non-empty and
at most 70 bytes long.
WriteField calls CreateFormField and then writes the given value.
*T : io.Closer
func NewWriter(w io.Writer) *Writer
partReader implements io.Reader by reading raw bytes directly from the
wrapped *Part, without doing any Transfer-Encoding decoding.
p*Part( T) Read(d []byte) (int, error)
T : io.Reader
stickyErrorReader is an io.Reader which never calls Read on its
underlying Reader once an error has been seen. (the io.Reader
interface's contract promises nothing about the return values of
Read calls after an error, yet this package does do multiple Reads
after error)
errerrorrio.Reader(*T) Read(p []byte) (n int, _ error)
*T : io.Reader
Package-Level Functions (total 8, in which 2 are exported)
NewReader creates a new multipart Reader reading from r using the
given MIME boundary.
The boundary is usually obtained from the "boundary" parameter of
the message's "Content-Type" header. Use mime.ParseMediaType to
parse such headers.
NewWriter returns a new multipart Writer with a random boundary,
writing to w.
matchAfterPrefix checks whether buf should be considered to match the boundary.
The prefix is "--boundary" or "\r\n--boundary" or "\n--boundary",
and the caller has verified already that bytes.HasPrefix(buf, prefix) is true.
matchAfterPrefix returns +1 if the buffer does match the boundary,
meaning the prefix is followed by a dash, space, tab, cr, nl, or end of input.
It returns -1 if the buffer definitely does NOT match the boundary,
meaning the prefix is followed by some other character.
For example, "--foobar" does not match "--foo".
It returns 0 more input needs to be read to make the decision,
meaning that len(buf) == len(prefix) and readErr == nil.
scanUntilBoundary scans buf to identify how much of it can be safely
returned as part of the Part body.
dashBoundary is "--boundary".
nlDashBoundary is "\r\n--boundary" or "\n--boundary", depending on what mode we are in.
The comments below (and the name) assume "\n--boundary", but either is accepted.
total is the number of bytes read out so far. If total == 0, then a leading "--boundary" is recognized.
readErr is the read error, if any, that followed reading the bytes in buf.
scanUntilBoundary returns the number of data bytes from buf that can be
returned as part of the Part body and also the error to return (if any)
once those data bytes are done.
skipLWSPChar returns b with leading spaces and tabs removed.
RFC 822 defines:
LWSP-char = SPACE / HTAB
Package-Level Variables (total 3, in which 1 are exported)
ErrMessageTooLarge is returned by ReadForm if the message form
data is too large to be processed.
Package-Level Constants (only one, which is unexported)
This constant needs to be at least 76 for this package to work correctly.
This is because \r\n--separator_of_len_70- would fill the buffer and it
wouldn't be safe to consume a single byte from it.
The pages are generated with Goldsv0.3.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.