Copyright 2011 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.

package multipart

import (
	
	
	
	
	
	
)
ErrMessageTooLarge is returned by ReadForm if the message form data is too large to be processed.
var ErrMessageTooLarge = errors.New("multipart: message too large")
TODO(adg,bradfitz): find a way to unify the DoS-prevention strategy here with that of the http package's ParseForm.
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.
func ( *Reader) ( int64) (*Form, error) {
	return .readForm()
}

func ( *Reader) ( int64) ( *Form,  error) {
	 := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
	defer func() {
		if  != nil {
			.RemoveAll()
		}
	}()
Reserve an additional 10 MB for non-file parts.
	 :=  + int64(10<<20)
	if  <= 0 {
		if  < 0 {
			 = 0
		} else {
			 = math.MaxInt64
		}
	}
	for {
		,  := .NextPart()
		if  == io.EOF {
			break
		}
		if  != nil {
			return nil, 
		}

		 := .FormName()
		if  == "" {
			continue
		}
		 := .FileName()

		var  bytes.Buffer

value, store as string in memory
			,  := io.CopyN(&, , +1)
			if  != nil &&  != io.EOF {
				return nil, 
			}
			 -= 
			if  < 0 {
				return nil, ErrMessageTooLarge
			}
			.Value[] = append(.Value[], .String())
			continue
		}
file, store in memory or on disk
		 := &FileHeader{
			Filename: ,
			Header:   .Header,
		}
		,  := io.CopyN(&, , +1)
		if  != nil &&  != io.EOF {
			return nil, 
		}
too big, write to disk and flush buffer
			,  := os.CreateTemp("", "multipart-")
			if  != nil {
				return nil, 
			}
			,  := io.Copy(, io.MultiReader(&, ))
			if  := .Close();  == nil {
				 = 
			}
			if  != nil {
				os.Remove(.Name())
				return nil, 
			}
			.tmpfile = .Name()
			.Size = 
		} else {
			.content = .Bytes()
			.Size = int64(len(.content))
			 -= 
			 -= 
		}
		.File[] = append(.File[], )
	}

	return , nil
}
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.
type Form struct {
	Value map[string][]string
	File  map[string][]*FileHeader
}
RemoveAll removes any temporary files associated with a Form.
func ( *Form) () error {
	var  error
	for ,  := range .File {
		for ,  := range  {
			if .tmpfile != "" {
				 := os.Remove(.tmpfile)
				if  != nil &&  == nil {
					 = 
				}
			}
		}
	}
	return 
}
A FileHeader describes a file part of a multipart request.
Open opens and returns the FileHeader's associated File.
func ( *FileHeader) () (File, error) {
	if  := .content;  != nil {
		 := io.NewSectionReader(bytes.NewReader(), 0, int64(len()))
		return sectionReadCloser{}, nil
	}
	return os.Open(.tmpfile)
}
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.
type File interface {
	io.Reader
	io.ReaderAt
	io.Seeker
	io.Closer
}
helper types to turn a []byte into a File

type sectionReadCloser struct {
	*io.SectionReader
}

func ( sectionReadCloser) () error {
	return nil