github.com/aarzilli/tools@v0.0.0-20151123112009-0d27094f75e0/net/http/upload/10_post_cli.go (about)

     1  package upload
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"log"
     8  	"mime/multipart"
     9  	"net/http"
    10  	"net/textproto"
    11  	"os"
    12  	"path/filepath"
    13  	"strings"
    14  )
    15  
    16  // CreateFilePostRequest2 prepares a multipart
    17  // file upload POST request
    18  func CreateFilePostRequest(
    19  	url, fileParamName, filePath string,
    20  	extraParams map[string]string,
    21  ) (*http.Request, error) {
    22  
    23  	// try opening the file
    24  	file, err := os.Open(filePath)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  	defer file.Close()
    29  
    30  	// first 512 bytes are used to evaluate mime type
    31  	first512 := make([]byte, 512)
    32  	file.Read(first512)
    33  	file.Seek(0, 0)
    34  	ct := http.DetectContentType(first512)
    35  	log.Println("detected", ct)
    36  
    37  	// prepare request body buffer
    38  	body := &bytes.Buffer{}
    39  
    40  	wrtr := multipart.NewWriter(body)
    41  
    42  	// append extra params
    43  	for param, val := range extraParams {
    44  		err = wrtr.WriteField(param, val)
    45  		if err != nil {
    46  			return nil, err
    47  		}
    48  	}
    49  
    50  	// create a multipart file header with the given param name and file
    51  	h := make(textproto.MIMEHeader)
    52  	cd := fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
    53  		escapeQuotes(fileParamName), escapeQuotes(filepath.Base(filePath)))
    54  	h.Set("Content-Disposition", cd)
    55  	h.Set("Content-Type", ct)
    56  
    57  	formfilePart, err := wrtr.CreatePart(h)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	// write the file to the part
    63  	num, err := io.Copy(formfilePart, file)
    64  	log.Println("copied", num, "bytes")
    65  
    66  	// the writer must be closed to finalize the file entry
    67  	err = wrtr.Close()
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	// finally create the request
    73  	req, err := http.NewRequest("POST", url, body)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  
    78  	// set type & boundary
    79  	req.Header.Set("Content-Type", wrtr.FormDataContentType())
    80  
    81  	return req, err
    82  
    83  }
    84  
    85  var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
    86  
    87  func escapeQuotes(s string) string {
    88  	return quoteEscaper.Replace(s)
    89  }