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?
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.
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.
HTTP Request action allows you to upload files on a specified service.
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 }
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With