Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I receive an uploaded file using a Golang net/http server?

I'm playing around with Mux and net/http. Lately, I'm trying to get a simple server with one endpoint to accept a file upload.

Here's the code I've got so far:

server.go

package main  import (     "fmt"     "github.com/gorilla/mux"     "log"     "net/http" )  func main() {     router := mux.NewRouter()     router.         Path("/upload").         Methods("POST").         HandlerFunc(UploadCsv)     fmt.Println("Starting")     log.Fatal(http.ListenAndServe(":8080", router)) } 

endpoint.go

package main  import (     "fmt"     "net/http" )  func UploadFile(w http.ResponseWriter, r *http.Request) {     err := r.ParseMultipartForm(5 * 1024 * 1024)     if err != nil {         panic(err)     }      fmt.Println(r.FormValue("fileupload")) } 

I think I've narrowed the issue down to actually retrieving the body from the request inside UploadFile. When I run this cURL command:

curl http://localhost:8080/upload -F "[email protected]" -vvv 

I get an empty response (as expected; I'm not printing to the ResponseWriter), but I just get a new (empty) line printed at the prompt where I'm running the server, instead of the request body.

I'm sending the file as multipart (AFAIK, implied by using -F rather than -d in cURL), and cURL's verbose output is showing 502 bytes sent:

$ curl http://localhost:8080/upload -F "[email protected]" -vvv *   Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 8080 (#0) > POST /upload HTTP/1.1 > Host: localhost:8080 > User-Agent: curl/7.51.0 > Accept: */* > Content-Length: 520 > Expect: 100-continue > Content-Type: multipart/form-data; boundary=------------------------b578878d86779dc5 >  < HTTP/1.1 100 Continue < HTTP/1.1 200 OK < Date: Fri, 18 Nov 2016 19:01:50 GMT < Content-Length: 0 < Content-Type: text/plain; charset=utf-8 <  * Curl_http_done: called premature == 0 * Connection #0 to host localhost left intact 

What's the proper way to receive files uploaded as multipart form data using a net/http server in Go?

like image 823
user7179784 Avatar asked Nov 18 '16 19:11

user7179784


People also ask

How do I upload a file to Golang?

Go to localhost:8080/upload, and you will see a form to upload a file. After selecting a file and clicking upload, the file should be created in your local filesystem.

How do I read a file in Golang?

The simplest way of reading a text or binary file in Go is to use the ReadFile() function from the os package. This function reads the entire content of the file into a byte slice, so you should be careful when trying to read a large file - in this case, you should read the file line by line or in chunks.

Which HTTP method is used for file upload?

HTTP Request action allows you to upload files on a specified service.


2 Answers

Here's a quick example

func ReceiveFile(w http.ResponseWriter, r *http.Request) {     r.ParseMultipartForm(32 << 20) // limit your max input length!     var buf bytes.Buffer     // in your case file would be fileupload     file, header, err := r.FormFile("file")     if err != nil {         panic(err)     }     defer file.Close()     name := strings.Split(header.Filename, ".")     fmt.Printf("File name %s\n", name[0])     // Copy the file data to my buffer     io.Copy(&buf, file)     // do something with the contents...     // I normally have a struct defined and unmarshal into a struct, but this will     // work as an example     contents := buf.String()     fmt.Println(contents)     // I reset the buffer in case I want to use it again     // reduces memory allocations in more intense projects     buf.Reset()     // do something else     // etc write header     return } 
like image 186
reticentroot Avatar answered Oct 02 '22 06:10

reticentroot


You should use FormFile instead of FormValue:

file, fileHeader, err := r.FormFile("fileupload") defer file.Close()  // copy example f, err := os.OpenFile("./downloaded", os.O_WRONLY|os.O_CREATE, 0666) defer f.Close() io.Copy(f, file) 
like image 29
Alex Pliutau Avatar answered Oct 02 '22 04:10

Alex Pliutau