Fragment Description:

Files uploading is straightforward.
On the client side:
a html Form with an input of type='file'.
On the server side:
a handler processing an io.MultireaderPart.
It is recommended to use a mime/multipart.Reader exposed by r.MultipartReader() instead of the other possibility:
This approach has the advantage that it doesn't write to a temporary location on the disk, as would r.MultiparseForm().


Last update, on 2016, Mon 4 Jan, 18:30:06

/* ... <== see fragment description ... */

package main

import (

// compiling/caching the template
var templates = template.Must(template.New("tmpl").Parse(`
    <title>File Upload Demo</title>
   body {
        font-family: Sans-serif;
        padding-top: 40px;
        padding-bottom: 40px;
        background-color: #ffffff;
   h1 {text-align: center; margin-bottom: 30px;}
   .message {font-weight:bold}
   fieldset {width:50%}
    <div class="container">
      <h1>File Upload Demo</h1>
      <div class="message">{{.}}</div>
      <form class="form-signin" method="post" action="/upload" enctype="multipart/form-data">
            <input type="file" name="myfiles" id="myfiles" multiple="multiple">
            <input type="submit" name="submit" value="Submit">

func uploadHandler(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    // GET to display the upload form.
    case "GET":
        err := templates.Execute(w, nil)
        if err != nil {
        // POST analyzes each part of the MultiPartReader (ie the uploaded file(s))
        // and saves them to disk.
    case "POST":
        // grab the request.MultipartReader
        reader, err := r.MultipartReader()
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
        // copy each part to destination.
        for {
            part, err := reader.NextPart()
            if err == io.EOF {
            // if part.FileName() is empty, skip this iteration.
            if part.FileName() == "" {

            // prepare the dst
            dst, err := os.Create("./" + part.FileName())
            defer dst.Close()
            if err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)

            // copy the part to dst
            if _, err := io.Copy(dst, part); err != nil {
                http.Error(w, err.Error(), http.StatusInternalServerError)
        // displaying a success message.
        err = templates.Execute(w, "Upload successful.")
        if err != nil {
func main() {
    http.HandleFunc("/upload", uploadHandler)
    log.Print("Listening on port:8082...")
    // Listen on port 8080
    http.ListenAndServe(":8082", nil)