mirror of
https://github.com/golang/go
synced 2024-11-19 23:04:40 -07:00
multipart: add FileName accessor on Part
R=rsc, adg CC=golang-dev https://golang.org/cl/4426074
This commit is contained in:
parent
bc926713c7
commit
ef94520380
@ -41,10 +41,7 @@ func (r *multiReader) ReadForm(maxMemory int64) (f *Form, err os.Error) {
|
|||||||
if name == "" {
|
if name == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var filename string
|
filename := p.FileName()
|
||||||
if p.dispositionParams != nil {
|
|
||||||
filename = p.dispositionParams["filename"]
|
|
||||||
}
|
|
||||||
|
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ import (
|
|||||||
|
|
||||||
var headerRegexp *regexp.Regexp = regexp.MustCompile("^([a-zA-Z0-9\\-]+): *([^\r\n]+)")
|
var headerRegexp *regexp.Regexp = regexp.MustCompile("^([a-zA-Z0-9\\-]+): *([^\r\n]+)")
|
||||||
|
|
||||||
|
var emptyParams = make(map[string]string)
|
||||||
|
|
||||||
// Reader is an iterator over parts in a MIME multipart body.
|
// Reader is an iterator over parts in a MIME multipart body.
|
||||||
// Reader's underlying parser consumes its input as needed. Seeking
|
// Reader's underlying parser consumes its input as needed. Seeking
|
||||||
// isn't supported.
|
// isn't supported.
|
||||||
@ -51,6 +53,7 @@ type Part struct {
|
|||||||
buffer *bytes.Buffer
|
buffer *bytes.Buffer
|
||||||
mr *multiReader
|
mr *multiReader
|
||||||
|
|
||||||
|
disposition string
|
||||||
dispositionParams map[string]string
|
dispositionParams map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,21 +62,33 @@ type Part struct {
|
|||||||
func (p *Part) FormName() string {
|
func (p *Part) FormName() string {
|
||||||
// See http://tools.ietf.org/html/rfc2183 section 2 for EBNF
|
// See http://tools.ietf.org/html/rfc2183 section 2 for EBNF
|
||||||
// of Content-Disposition value format.
|
// of Content-Disposition value format.
|
||||||
if p.dispositionParams != nil {
|
if p.dispositionParams == nil {
|
||||||
return p.dispositionParams["name"]
|
p.parseContentDisposition()
|
||||||
}
|
}
|
||||||
v := p.Header.Get("Content-Disposition")
|
if p.disposition != "form-data" {
|
||||||
if v == "" {
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if d, params := mime.ParseMediaType(v); d != "form-data" {
|
|
||||||
return ""
|
|
||||||
} else {
|
|
||||||
p.dispositionParams = params
|
|
||||||
}
|
|
||||||
return p.dispositionParams["name"]
|
return p.dispositionParams["name"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FileName returns the filename parameter of the Part's
|
||||||
|
// Content-Disposition header.
|
||||||
|
func (p *Part) FileName() string {
|
||||||
|
if p.dispositionParams == nil {
|
||||||
|
p.parseContentDisposition()
|
||||||
|
}
|
||||||
|
return p.dispositionParams["filename"]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Part) parseContentDisposition() {
|
||||||
|
v := p.Header.Get("Content-Disposition")
|
||||||
|
p.disposition, p.dispositionParams = mime.ParseMediaType(v)
|
||||||
|
if p.dispositionParams == nil {
|
||||||
|
p.dispositionParams = emptyParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewReader creates a new multipart Reader reading from r using the
|
// NewReader creates a new multipart Reader reading from r using the
|
||||||
// given MIME boundary.
|
// given MIME boundary.
|
||||||
func NewReader(reader io.Reader, boundary string) Reader {
|
func NewReader(reader io.Reader, boundary string) Reader {
|
||||||
|
@ -56,24 +56,25 @@ func expectEq(t *testing.T, expected, actual, what string) {
|
|||||||
what, escapeString(actual), len(actual), escapeString(expected), len(expected))
|
what, escapeString(actual), len(actual), escapeString(expected), len(expected))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFormName(t *testing.T) {
|
func TestNameAccessors(t *testing.T) {
|
||||||
p := new(Part)
|
tests := [...][3]string{
|
||||||
p.Header = make(map[string][]string)
|
{`form-data; name="foo"`, "foo", ""},
|
||||||
tests := [...][2]string{
|
{` form-data ; name=foo`, "foo", ""},
|
||||||
{`form-data; name="foo"`, "foo"},
|
{`FORM-DATA;name="foo"`, "foo", ""},
|
||||||
{` form-data ; name=foo`, "foo"},
|
{` FORM-DATA ; name="foo"`, "foo", ""},
|
||||||
{`FORM-DATA;name="foo"`, "foo"},
|
{` FORM-DATA ; name="foo"`, "foo", ""},
|
||||||
{` FORM-DATA ; name="foo"`, "foo"},
|
{` FORM-DATA ; name=foo`, "foo", ""},
|
||||||
{` FORM-DATA ; name="foo"`, "foo"},
|
{` FORM-DATA ; filename="foo.txt"; name=foo; baz=quux`, "foo", "foo.txt"},
|
||||||
{` FORM-DATA ; name=foo`, "foo"},
|
{` not-form-data ; filename="bar.txt"; name=foo; baz=quux`, "", "bar.txt"},
|
||||||
{` FORM-DATA ; filename="foo.txt"; name=foo; baz=quux`, "foo"},
|
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for i, test := range tests {
|
||||||
|
p := &Part{Header: make(map[string][]string)}
|
||||||
p.Header.Set("Content-Disposition", test[0])
|
p.Header.Set("Content-Disposition", test[0])
|
||||||
expected := test[1]
|
if g, e := p.FormName(), test[1]; g != e {
|
||||||
actual := p.FormName()
|
t.Errorf("test %d: FormName() = %q; want %q", i, g, e)
|
||||||
if actual != expected {
|
}
|
||||||
t.Errorf("expected \"%s\"; got: \"%s\"", expected, actual)
|
if g, e := p.FileName(), test[2]; g != e {
|
||||||
|
t.Errorf("test %d: FileName() = %q; want %q", i, g, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user