Send a file through a cURL form with `net/http`

Hello there!

I’m trying to make a POST request equivalent to curl -d "file=@filename" https://xxx/upload

I tried the following:

formData := url.Values{
		"file": {"@" + filename},
	//req, err := http.NewRequest("POST", url, strings.NewReader(form.Encode()))
	resp, err := http.PostForm("", formData)

I believe I should use CreateFormFile but its documentation is somewhat confusing.

Any help would be appreciated!

Hi, Vinicius,

That “file=@filename” notation is specific to curl. In Go, you might need to handle reading the data yourself. I think this will do it (or at least, get you started):

func POSTFile(filename string) (*http.Response, error) {
    f, err := os.Open(filename)
    if err != nil {
        return nil, err
    defer f.Close()
    return POSTData(f)

func POSTData(r io.Reader) (*http.Response, error) {
    sb := strings.Builder{}
    if _, err := io.Copy(sb, r); err != nil {
        return nil, err
    formData := url.Values{
        "file": []string{sb.String()},
    return http.PostForm("", formData)

Note that this will only work if your file is text, but I think that matches curl’s -d, --data parameter’s usage.


Hello, Sean! Thanks a lot for your response.

I forgot to update this post but I eventually solved the problem with a method similar to the one you’ve shown:

mpb := bytes.NewBuffer(nil)
mw := multipart.NewWriter(mpb)

partWriter, err := mw.CreateFormFile("file", filename)
fileReader, err := os.Open(filename)
io.Copy(partWriter, fileReader)

However, I still have a question about this. Does io.Copy actually copy the file’s content to the computer’s RAM? If it does, could there be a better way to upload large files?

Thanks again for your time!

This depends on the implementations of the involved buffers.

Though implementations usually strive to be implemented in a way that they don’t need to hold full content in memory, unless reading/writing directly from/to memory.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.