func PrepareUpload(media io.Reader, chunkSize int) (io.Reader, *MediaBuffer) {
	if chunkSize == 0 {  
		return media, nil
	}
	mb := NewMediaBuffer(media, chunkSize)
	rdr, _, _, err := mb.Chunk()
	if err == io.EOF {  
		return rdr, nil
	}
	return nil, mb
}
PrepareUpload determines whether the data in the supplied reader should be
uploaded in a single request, or in sequential chunks.
chunkSize is the size of the chunk that media should be split into.
If chunkSize is non-zero and the contents of media do not fit in a single
chunk (or there is an error reading media), then media will be returned as a
MediaBuffer.  Otherwise, media will be returned as a Reader.

After PrepareUpload has been called, media should no longer be used: the
media content should be accessed via one of the return values.
package gensupport
import (
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/textproto"
	"google.golang.org/api/googleapi"
)
const sniffBuffSize = 512
func newContentSniffer(r io.Reader) *contentSniffer {
	return &contentSniffer{r: r}
}
type contentSniffer struct {
	r     io.Reader
	start []byte  
	err   error   
	ctype   string  
	sniffed bool    
}
func (cs *contentSniffer) Read(p []byte) (n int, err error) {
	_, _ = cs.ContentType()
	if len(cs.start) > 0 {
		n := copy(p, cs.start)
		cs.start = cs.start[n:]
		return n, nil
	}
	if cs.err != nil {
		return 0, cs.err
	}
	return cs.r.Read(p)
}
func (cs *contentSniffer) ContentType() (string, bool) {
	if cs.sniffed {
		return cs.ctype, cs.ctype != ""
	}
	cs.sniffed = true
	cs.start, cs.err = ioutil.ReadAll(io.LimitReader(cs.r, sniffBuffSize))
	if cs.err != nil {
		return "", false
	}
	cs.ctype = http.DetectContentType(cs.start)
	return cs.ctype, true
}
func DetermineContentType(media io.Reader, ctype string) (io.Reader, string) {
	if ctype != "" {
		return media, ctype
	}
	if typer, ok := media.(googleapi.ContentTyper); ok {
		return media, typer.ContentType()
	}
	sniffer := newContentSniffer(media)
	if ctype, ok := sniffer.ContentType(); ok {
		return sniffer, ctype
	}
	return sniffer, ""
}
type typeReader struct {
	io.Reader
	typ string
}
type multipartReader struct {
	pr       *io.PipeReader
	pipeOpen bool
	ctype    string
}
func newMultipartReader(parts []typeReader) *multipartReader {
	mp := &multipartReader{pipeOpen: true}
	var pw *io.PipeWriter
	mp.pr, pw = io.Pipe()
	mpw := multipart.NewWriter(pw)
	mp.ctype = "multipart/related; boundary=" + mpw.Boundary()
	go func() {
		for _, part := range parts {
			w, err := mpw.CreatePart(typeHeader(part.typ))
			if err != nil {
				mpw.Close()
				pw.CloseWithError(fmt.Errorf("googleapi: CreatePart failed: %v", err))
				return
			}
			_, err = io.Copy(w, part.Reader)
			if err != nil {
				mpw.Close()
				pw.CloseWithError(fmt.Errorf("googleapi: Copy failed: %v", err))
				return
			}
		}
		mpw.Close()
		pw.Close()
	}()
	return mp
}
func (mp *multipartReader) Read(data []byte) (n int, err error) {
	return mp.pr.Read(data)
}
func (mp *multipartReader) Close() error {
	if !mp.pipeOpen {
		return nil
	}
	mp.pipeOpen = false
	return mp.pr.Close()
}
func CombineBodyMedia(body io.Reader, bodyContentType string, media io.Reader, mediaContentType string) (io.ReadCloser, string) {
	mp := newMultipartReader([]typeReader{
		{body, bodyContentType},
		{media, mediaContentType},
	})
	return mp, mp.ctype
}
func typeHeader(contentType string) textproto.MIMEHeader {
	h := make(textproto.MIMEHeader)
	if contentType != "" {
		h.Set("Content-Type", contentType)
	}
	return h
}