Accessing Uploaded Files in Golang

17,183

Solution 1

Answer Download the latest golang release.

I experienced the problem before, using the old golang versions, I do not know what happened, but with the latest golang its working. =)

My upload handler code below... Full code at: http://noypi-linux.blogspot.com/2014/07/golang-web-server-basic-operatons-using.html

  // parse request  
  const _24K = (1 << 10) * 24  
  if err = req.ParseMultipartForm(_24K); nil != err {  
       status = http.StatusInternalServerError  
       return  
  }  
  for _, fheaders := range req.MultipartForm.File {  
       for _, hdr := range fheaders {  
            // open uploaded  
            var infile multipart.File  
            if infile, err = hdr.Open(); nil != err {  
                 status = http.StatusInternalServerError  
                 return  
            }  
            // open destination  
            var outfile *os.File  
            if outfile, err = os.Create("./uploaded/" + hdr.Filename); nil != err {  
                 status = http.StatusInternalServerError  
                 return  
            }  
            // 32K buffer copy  
            var written int64  
            if written, err = io.Copy(outfile, infile); nil != err {  
                 status = http.StatusInternalServerError  
                 return  
            }  
            res.Write([]byte("uploaded file:" + hdr.Filename + ";length:" + strconv.Itoa(int(written))))  
       }  
  }  

Solution 2

If you know they key of the file upload you can make it a bit simpler I think (this is not tested):

infile, header, err := r.FormFile("file")
if err != nil {
    http.Error(w, "Error parsing uploaded file: "+err.Error(), http.StatusBadRequest)
    return
}

// THIS IS VERY INSECURE! DO NOT DO THIS!
outfile, err := os.Create("./uploaded/" + header.Filename)
if err != nil {
    http.Error(w, "Error saving file: "+err.Error(), http.StatusBadRequest)
    return
}

_, err = io.Copy(outfile, infile)
if err != nil {
    http.Error(w, "Error saving file: "+err.Error(), http.StatusBadRequest)
    return
}

fmt.Fprintln(w, "Ok")
Share:
17,183
Micah
Author by

Micah

CTO @ gooten.com

Updated on July 24, 2022

Comments

  • Micah
    Micah almost 2 years

    I'm having issues with accessing files i upload w/ golang. I'm really new to the language and have gone through more than a few attempts-- can't find any answers to this online either.

    What am i doing wrong? In this code, i never get to the block where it lists the # of files uploaded.

    func handler(w http.ResponseWriter, r *http.Request) {
      fmt.Println("handling req...")
    
      if r.Method =="GET"{
        fmt.Println("GET req...")
    
      } else {
    
        //parse the multipart stuff if there
        err := r.ParseMultipartForm(15485760)
    
        //
        if err == nil{
            form:=r.MultipartForm
            if form==nil {
                fmt.Println("no files...")
    
            } else {
                defer form.RemoveAll()
                // i never see this actually occur
                fmt.Printf("%d files",len(form.File))
            }
        } else {
            http.Error(w,err.Error(),http.StatusInternalServerError)
            fmt.Println(err.Error())
        }
      }
    
      //fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
      fmt.Println("leaving...")
    }
    

    Update

    I was able to get the above code to work. Which is great. The answer below shows how to do it async, which may be a better code sample than mine.

  • THUNDERGROOVE
    THUNDERGROOVE about 9 years
    What exactly is insecure about the way you create the file? What's the preferred method?
  • Timmmm
    Timmmm about 9 years
    The filename might be ../../../../../etc/passwd or whatever. Basically I didn't sanitise the filename or check that no other file existed there already. It may be the case the go removes \ and / from filenames but I wouldn't rely on it.
  • THUNDERGROOVE
    THUNDERGROOVE about 9 years
    That's what I thought. Thanks! I suppose the best thing to do would be to not allow / or \ Am I correct in thinking that or is there more to worry about?
  • Timmmm
    Timmmm about 9 years
    That should do it (at least on non-windows platforms). I would whitelist characters I know are safe and uri-encode the rest.
  • Gonzalo Serrano
    Gonzalo Serrano over 7 years
    const _24K = (1 << 20) * 24 <-- that's 24MB isn't it? 2^20 = 1MB
  • 18augst
    18augst over 6 years
    Should I delete files in temporary directory after copy? I've noticed files, which size is greater than _24K (or whatever), appear in my '/tmp' dir and I really have no idea how I can delete them os.Remove(hdr.Filename) does nothing, just can not find temporary file (since its name is not the same as uploaded file has).