可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to upload images from my computer to a website using go. Usually, I use a bash script who send file a key to the serveur:
curl -F "image"=@"IMAGEFILE" -F "key"="KEY" URL
it's work fine, but I'm trying to convert this request into my golang program.
http://matt.aimonetti.net/posts/2013/07/01/golang-multipart-file-upload-example/
I tried this link and many other. But for each code that I try, the response for the server is "no image sended". And I've no idea why. If someone know what's happend with the exemple above.
Thanks
回答1:
Here's some sample code.
In short, you'll need to use the mime/multipart package to build the form.
package sample import ( "bytes" "fmt" "io" "mime/multipart" "net/http" "os" ) func Upload(url, file string) (err error) { // Prepare a form that you will submit to that URL. var b bytes.Buffer w := multipart.NewWriter(&b) // Add your image file f, err := os.Open(file) if err != nil { return } defer f.Close() fw, err := w.CreateFormFile("image", file) if err != nil { return } if _, err = io.Copy(fw, f); err != nil { return } // Add the other fields if fw, err = w.CreateFormField("key"); err != nil { return } if _, err = fw.Write([]byte("KEY")); err != nil { return } // 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 client := &http.Client{} 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 }
回答2:
Regarding attila-o's post, the request header doesn't have the boundary since the Writer is closed already.
// after the close, the bounday will be nil. w.Close() ... req.Header.Set("Content-Type", w.FormDataContentType())
So, it should close after the set, I think.
req.Header.Set("Content-Type", w.FormDataContentType()) w.Close()
回答3:
I have found this tutorial very helpful to clarify my confusions about file uploading in Go.
Basically you upload the file via ajax using form-data on a client and use the following small snippet of Go code on the server:
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)
Here r is *http.Request. P.S. this just stores the file in the same folder and does not perform any security checks.