application - ¿Cómo puedo recibir un archivo cargado utilizando un servidor Golang net/http?
web application golang (3)
Aquí hay un ejemplo rápido
func ReceiveFile(w http.ResponseWriter, r *http.Request) {
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
}
Estoy jugando con Mux y net/http
. Últimamente, estoy tratando de obtener un servidor simple con un punto final para aceptar la carga de un archivo.
Aquí está el código que tengo hasta ahora:
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"))
}
Creo que he reducido el problema para recuperar realmente el cuerpo de la solicitud dentro de UploadFile
. Cuando ejecuto este comando cURL:
curl http://localhost:8080/upload -F "[email protected]" -vvv
Recibo una respuesta en blanco (como se esperaba, no estoy imprimiendo en el ResponseWriter
), pero solo imprimo una nueva línea (vacía) en el indicador donde ejecuto el servidor, en lugar del cuerpo de la solicitud.
Estoy enviando el archivo como multiparte (AFAIK, implícito mediante el uso de -F
lugar de -d
en cURL), y la salida detallada de cURL muestra 502 bytes enviados:
$ 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
¿Cuál es la forma correcta de recibir archivos cargados como datos de formulario de varias partes utilizando un servidor net/http
en Go?
Aquí hay una función que escribí para ayudarme a subir mis archivos. Puede consultar la versión completa aquí. Cómo subir archivos en golang
package helpers
import (
"net/http"
"os"
"io"
)
func FileUpload(r *http.Request) (string, error) {
//this function returns the filename(to save in database) of the saved file or an error if it occurs
r.ParseMultipartForm(32 << 20)
//ParseMultipartForm parses a request body as multipart/form-data
var file_name string
var errors error
file, handler, err := r.FormFile("file")//retrieve the file from form data
defer file.Close() //close the file when we finish
if err != nil {
errors = err
}
//this is path which we want to store the file
f, err := os.OpenFile("./images/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
errors = err
}
file_name = handler.Filename
defer f.Close()
io.Copy(f, file)
//here we save our file to our path
return file_name, errors
}
Debe usar FormFile
lugar de FormValue
:
file, handler, err := r.FormFile("fileupload")
defer file.Close()
// copy example
f, err := os.OpenFile("./test/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
defer f.Close()
io.Copy(f, file)