file upload - datos POST de golang utilizando el contenido de tipo multipart/form-data
file-upload curl (3)
Aquí hay un código de muestra.
En resumen, deberá usar el paquete mime/multipart
para compilar el formulario.
package main
import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/http/httptest"
"net/http/httputil"
"os"
"strings"
)
func main() {
var client *http.Client
var remoteURL string
{
//setup a mocked http client.
ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b, err := httputil.DumpRequest(r, true)
if err != nil {
panic(err)
}
fmt.Printf("%s", b)
}))
defer ts.Close()
client = ts.Client()
remoteURL = ts.URL
}
//prepare the reader instances to encode
values := map[string]io.Reader{
"file": mustOpen("main.go"), // lets assume its this file
"other": strings.NewReader("hello world!"),
}
err := Upload(client, remoteURL, values)
if err != nil {
panic(err)
}
}
func Upload(client *http.Client, url string, values map[string]io.Reader) (err error) {
// Prepare a form that you will submit to that URL.
var b bytes.Buffer
w := multipart.NewWriter(&b)
for key, r := range values {
var fw io.Writer
if x, ok := r.(io.Closer); ok {
defer x.Close()
}
// Add an image file
if x, ok := r.(*os.File); ok {
if fw, err = w.CreateFormFile(key, x.Name()); err != nil {
return
}
} else {
// Add other fields
if fw, err = w.CreateFormField(key); err != nil {
return
}
}
if _, err = io.Copy(fw, r); err != nil {
return err
}
}
// Don''t forget to close the multipart writer.
// If you don''t close it, your request will be missing the terminating boundary.
w.Close()
// Now that you have a form, you can submit it to your handler.
req, err := http.NewRequest("POST", url, &b)
if err != nil {
return
}
// Don''t forget to set the content type, this will contain the boundary.
req.Header.Set("Content-Type", w.FormDataContentType())
// Submit the request
res, err := client.Do(req)
if err != nil {
return
}
// Check the response
if res.StatusCode != http.StatusOK {
err = fmt.Errorf("bad status: %s", res.Status)
}
return
}
func mustOpen(f string) *os.File {
r, err := os.Open(f)
if err != nil {
panic(err)
}
return r
}
Estoy intentando subir imágenes de mi computadora a un sitio web usando ir. Por lo general, utilizo un script bash que envía una clave al servidor:
curl -F "image"=@"IMAGEFILE" -F "key"="KEY" URL
funciona bien, pero estoy tratando de convertir esta solicitud en mi programa de golang.
http://matt.aimonetti.net/posts/2013/07/01/golang-multipart-file-upload-example/
Intenté este enlace y muchos otros. Pero para cada código que intento, la respuesta para el servidor es "sin imagen enviada". Y no tengo idea de por qué. Si alguien sabe lo que pasó con el ejemplo anterior.
Gracias
Con respecto a la publicación de attila-o, el encabezado de la solicitud no tiene el límite ya que el escritor está cerrado.
// after the close, the bounday will be nil.
w.Close()
...
req.Header.Set("Content-Type", w.FormDataContentType())
Entonces, debería cerrarse después del set, creo.
req.Header.Set("Content-Type", w.FormDataContentType())
w.Close()
He encontrado este tutorial muy útil para aclarar mis confusiones sobre la carga de archivos en Go.
Básicamente, cargue el archivo a través de ajax usando form-data
en un cliente y use el siguiente pequeño fragmento de código Go en el servidor:
file, handler, err := r.FormFile("img") // img is the key of the form-data
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
fmt.Println("File is good")
fmt.Println(handler.Filename)
fmt.Println()
fmt.Println(handler.Header)
f, err := os.OpenFile(handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
io.Copy(f, file)
Aquí está r
*http.Request
. PD esto solo almacena el archivo en la misma carpeta y no realiza ninguna comprobación de seguridad.