summaryrefslogtreecommitdiff
path: root/devdocs/go/mime%2Fmultipart%2Findex.html
blob: 25e5e1fe5ea752b15addd7b12fa51bb385b5c267 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<h1> Package multipart  </h1>     <ul id="short-nav">
<li><code>import "mime/multipart"</code></li>
<li><a href="#pkg-overview" class="overviewLink">Overview</a></li>
<li><a href="#pkg-index" class="indexLink">Index</a></li>
<li><a href="#pkg-examples" class="examplesLink">Examples</a></li>
</ul>     <h2 id="pkg-overview">Overview </h2> <p>Package multipart implements MIME multipart parsing, as defined in RFC 2046. </p>
<p>The implementation is sufficient for HTTP (RFC 2388) and the multipart bodies generated by popular browsers. </p>
<h3 id="hdr-Limits">Limits</h3> <p>To protect against malicious inputs, this package sets limits on the size of the MIME data it processes. </p>
<p>Reader.NextPart and Reader.NextRawPart limit the number of headers in a part to 10000 and Reader.ReadForm limits the total number of headers in all FileHeaders to 10000. These limits may be adjusted with the GODEBUG=multipartmaxheaders=&lt;values&gt; setting. </p>
<p>Reader.ReadForm further limits the number of parts in a form to 1000. This limit may be adjusted with the GODEBUG=multipartmaxparts=&lt;value&gt; setting. </p>
<p>Copyright 2023 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. </p>     <h2 id="pkg-index">Index </h2>  <ul id="manual-nav">
<li><a href="#pkg-variables">Variables</a></li>
<li><a href="#File">type File</a></li>
<li><a href="#FileHeader">type FileHeader</a></li>
<li> <a href="#FileHeader.Open">func (fh *FileHeader) Open() (File, error)</a>
</li>
<li><a href="#Form">type Form</a></li>
<li> <a href="#Form.RemoveAll">func (f *Form) RemoveAll() error</a>
</li>
<li><a href="#Part">type Part</a></li>
<li> <a href="#Part.Close">func (p *Part) Close() error</a>
</li>
<li> <a href="#Part.FileName">func (p *Part) FileName() string</a>
</li>
<li> <a href="#Part.FormName">func (p *Part) FormName() string</a>
</li>
<li> <a href="#Part.Read">func (p *Part) Read(d []byte) (n int, err error)</a>
</li>
<li><a href="#Reader">type Reader</a></li>
<li> <a href="#NewReader">func NewReader(r io.Reader, boundary string) *Reader</a>
</li>
<li> <a href="#Reader.NextPart">func (r *Reader) NextPart() (*Part, error)</a>
</li>
<li> <a href="#Reader.NextRawPart">func (r *Reader) NextRawPart() (*Part, error)</a>
</li>
<li> <a href="#Reader.ReadForm">func (r *Reader) ReadForm(maxMemory int64) (*Form, error)</a>
</li>
<li><a href="#Writer">type Writer</a></li>
<li> <a href="#NewWriter">func NewWriter(w io.Writer) *Writer</a>
</li>
<li> <a href="#Writer.Boundary">func (w *Writer) Boundary() string</a>
</li>
<li> <a href="#Writer.Close">func (w *Writer) Close() error</a>
</li>
<li> <a href="#Writer.CreateFormField">func (w *Writer) CreateFormField(fieldname string) (io.Writer, error)</a>
</li>
<li> <a href="#Writer.CreateFormFile">func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error)</a>
</li>
<li> <a href="#Writer.CreatePart">func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, error)</a>
</li>
<li> <a href="#Writer.FormDataContentType">func (w *Writer) FormDataContentType() string</a>
</li>
<li> <a href="#Writer.SetBoundary">func (w *Writer) SetBoundary(boundary string) error</a>
</li>
<li> <a href="#Writer.WriteField">func (w *Writer) WriteField(fieldname, value string) error</a>
</li>
</ul> <div id="pkg-examples"> <h3>Examples</h3>  <dl> <dd><a class="exampleLink" href="#example_NewReader">NewReader</a></dd> </dl> </div> <h3>Package files</h3> <p>  <span>formdata.go</span> <span>multipart.go</span> <span>readmimeheader.go</span> <span>writer.go</span>  </p>   <h2 id="pkg-variables">Variables</h2> <p>ErrMessageTooLarge is returned by ReadForm if the message form data is too large to be processed. </p>
<pre data-language="go">var ErrMessageTooLarge = errors.New("multipart: message too large")</pre> <h2 id="File">type <span>File</span>  </h2> <p>File is an interface to access the file part of a multipart message. Its contents may be either stored in memory or on disk. If stored on disk, the File's underlying concrete type will be an *os.File. </p>
<pre data-language="go">type File interface {
    io.Reader
    io.ReaderAt
    io.Seeker
    io.Closer
}</pre> <h2 id="FileHeader">type <span>FileHeader</span>  </h2> <p>A FileHeader describes a file part of a multipart request. </p>
<pre data-language="go">type FileHeader struct {
    Filename string
    Header   textproto.MIMEHeader
    Size     int64 // Go 1.9
    // contains filtered or unexported fields
}
</pre> <h3 id="FileHeader.Open">func (*FileHeader) <span>Open</span>  </h3> <pre data-language="go">func (fh *FileHeader) Open() (File, error)</pre> <p>Open opens and returns the FileHeader's associated File. </p>
<h2 id="Form">type <span>Form</span>  </h2> <p>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. </p>
<pre data-language="go">type Form struct {
    Value map[string][]string
    File  map[string][]*FileHeader
}
</pre> <h3 id="Form.RemoveAll">func (*Form) <span>RemoveAll</span>  </h3> <pre data-language="go">func (f *Form) RemoveAll() error</pre> <p>RemoveAll removes any temporary files associated with a Form. </p>
<h2 id="Part">type <span>Part</span>  </h2> <p>A Part represents a single part in a multipart body. </p>
<pre data-language="go">type Part struct {
    // 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"
    Header textproto.MIMEHeader
    // contains filtered or unexported fields
}
</pre> <h3 id="Part.Close">func (*Part) <span>Close</span>  </h3> <pre data-language="go">func (p *Part) Close() error</pre> <h3 id="Part.FileName">func (*Part) <span>FileName</span>  </h3> <pre data-language="go">func (p *Part) FileName() string</pre> <p>FileName returns the filename parameter of the Part's Content-Disposition header. If not empty, the filename is passed through filepath.Base (which is platform dependent) before being returned. </p>
<h3 id="Part.FormName">func (*Part) <span>FormName</span>  </h3> <pre data-language="go">func (p *Part) FormName() string</pre> <p>FormName returns the name parameter if p has a Content-Disposition of type "form-data". Otherwise it returns the empty string. </p>
<h3 id="Part.Read">func (*Part) <span>Read</span>  </h3> <pre data-language="go">func (p *Part) Read(d []byte) (n int, err error)</pre> <p>Read reads the body of a part, after its headers and before the next part (if any) begins. </p>
<h2 id="Reader">type <span>Reader</span>  </h2> <p>Reader is an iterator over parts in a MIME multipart body. Reader's underlying parser consumes its input as needed. Seeking isn't supported. </p>
<pre data-language="go">type Reader struct {
    // contains filtered or unexported fields
}
</pre> <h3 id="NewReader">func <span>NewReader</span>  </h3> <pre data-language="go">func NewReader(r io.Reader, boundary string) *Reader</pre> <p>NewReader creates a new multipart Reader reading from r using the given MIME boundary. </p>
<p>The boundary is usually obtained from the "boundary" parameter of the message's "Content-Type" header. Use mime.ParseMediaType to parse such headers. </p>   <h4 id="example_NewReader"> <span class="text">Example</span>
</h4> <p>Code:</p> <pre class="code" data-language="go">msg := &amp;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)
    }
}

</pre> <p>Output:</p> <pre class="output" data-language="go">Part "one": "A section"
Part "two": "And another"
</pre>   <h3 id="Reader.NextPart">func (*Reader) <span>NextPart</span>  </h3> <pre data-language="go">func (r *Reader) NextPart() (*Part, error)</pre> <p>NextPart returns the next part in the multipart or an error. When there are no more parts, the error io.EOF is returned. </p>
<p>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. </p>
<h3 id="Reader.NextRawPart">func (*Reader) <span>NextRawPart</span>  <span title="Added in Go 1.14">1.14</span> </h3> <pre data-language="go">func (r *Reader) NextRawPart() (*Part, error)</pre> <p>NextRawPart returns the next part in the multipart or an error. When there are no more parts, the error io.EOF is returned. </p>
<p>Unlike NextPart, it does not have special handling for "Content-Transfer-Encoding: quoted-printable". </p>
<h3 id="Reader.ReadForm">func (*Reader) <span>ReadForm</span>  </h3> <pre data-language="go">func (r *Reader) ReadForm(maxMemory int64) (*Form, error)</pre> <p>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. </p>
<h2 id="Writer">type <span>Writer</span>  </h2> <p>A Writer generates multipart messages. </p>
<pre data-language="go">type Writer struct {
    // contains filtered or unexported fields
}
</pre> <h3 id="NewWriter">func <span>NewWriter</span>  </h3> <pre data-language="go">func NewWriter(w io.Writer) *Writer</pre> <p>NewWriter returns a new multipart Writer with a random boundary, writing to w. </p>
<h3 id="Writer.Boundary">func (*Writer) <span>Boundary</span>  </h3> <pre data-language="go">func (w *Writer) Boundary() string</pre> <p>Boundary returns the Writer's boundary. </p>
<h3 id="Writer.Close">func (*Writer) <span>Close</span>  </h3> <pre data-language="go">func (w *Writer) Close() error</pre> <p>Close finishes the multipart message and writes the trailing boundary end line to the output. </p>
<h3 id="Writer.CreateFormField">func (*Writer) <span>CreateFormField</span>  </h3> <pre data-language="go">func (w *Writer) CreateFormField(fieldname string) (io.Writer, error)</pre> <p>CreateFormField calls CreatePart with a header using the given field name. </p>
<h3 id="Writer.CreateFormFile">func (*Writer) <span>CreateFormFile</span>  </h3> <pre data-language="go">func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error)</pre> <p>CreateFormFile is a convenience wrapper around CreatePart. It creates a new form-data header with the provided field name and file name. </p>
<h3 id="Writer.CreatePart">func (*Writer) <span>CreatePart</span>  </h3> <pre data-language="go">func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, error)</pre> <p>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. </p>
<h3 id="Writer.FormDataContentType">func (*Writer) <span>FormDataContentType</span>  </h3> <pre data-language="go">func (w *Writer) FormDataContentType() string</pre> <p>FormDataContentType returns the Content-Type for an HTTP multipart/form-data with this Writer's Boundary. </p>
<h3 id="Writer.SetBoundary">func (*Writer) <span>SetBoundary</span>  <span title="Added in Go 1.1">1.1</span> </h3> <pre data-language="go">func (w *Writer) SetBoundary(boundary string) error</pre> <p>SetBoundary overrides the Writer's default randomly-generated boundary separator with an explicit value. </p>
<p>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. </p>
<h3 id="Writer.WriteField">func (*Writer) <span>WriteField</span>  </h3> <pre data-language="go">func (w *Writer) WriteField(fieldname, value string) error</pre> <p>WriteField calls CreateFormField and then writes the given value. </p><div class="_attribution">
  <p class="_attribution-p">
    &copy; Google, Inc.<br>Licensed under the Creative Commons Attribution License 3.0.<br>
    <a href="http://golang.org/pkg/mime/multipart/" class="_attribution-link">http://golang.org/pkg/mime/multipart/</a>
  </p>
</div>