从golang代码将文件发送到Google Drive API会产生错误:类型为image / jpeg的内容不受支持

based on the Google Drive API docs the proper way of uploading a file is:

curl -v -H 'Authorization: Bearer mytoken' -F 'metadata={"name": "test3.jpeg"};type=application/json' -F file=@jpeg_image.jpeg 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart'

Now, I need to perform the same request from golang code, but I am having a hard time translating this to golang, here is the code I am using after several attempts:

// fileBytes are of type []byte
buffer := &bytes.Buffer{}
    multipartWriter := multipart.NewWriter(buffer)
    multipartWriter.WriteField("metadata", "{\"name\": \"test3.jpef\"};type=application/json")
    partHeader := textproto.MIMEHeader{}
    partHeader.Add("Content-Type", "image/jpeg")
    filePartWriter, _ := multipartWriter.CreatePart(partHeader)
    io.Copy(filePartWriter, bytes.NewReader(fileBytes))
    multipartWriter.Close()

    googleDriveRequest, _ := http.NewRequest(http.MethodPost, "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart", buffer)
    googleDriveRequest.Header.Add("Authorization", "Bearer "+accessToken)
    googleDriveRequest.Header.Add("Content-Type", multipartWriter.FormDataContentType())

    googleDriveAPIResponse, googleDriveAPIError := lib.HttpClient.Do(googleDriveRequest)

Using curl the request succeeds :

{
 "kind": "drive#file",
 "id": "1DwsbQGP3-QtS5p0iQqRtAjcCCsAfxzGD",
 "name": "test3.jpeg",
 "mimeType": "image/jpeg"
}

With Golang, I get a 400:

{
 \"error\": {
  \"errors\": [
   {
    \"domain\": \"global\",
    \"reason\": \"badContent\",
    \"message\": \"Unsupported content with type: image/jpeg \"
   }
  ],
  \"code\": 400,
  \"message\": \"Unsupported content with type: image/jpeg\"
 }
}

I also tried with different values for partHeader.Add("Content-Type", "image/jpeg"), I tried with application/x-www-form-urlencoded as well, I also commented out this line, and let golang do the detection, but still getting the same error.

Any suggestions or ideas?

Regards,

The problem is in the JSON metadata that you send. Here is a sample code (use proper error checking) that will work,

import (
    "bytes"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "mime/multipart"
    "net/http"
    "net/textproto"
)

func main() {
    accessToken := "YOUR-TOKEN"

    client := http.Client{}
    mediaData, _ := ioutil.ReadFile("test.png")

    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)

    // JSON Metadata (part-1)
    jsonMetadata := textproto.MIMEHeader{}
    metadata := `{"name": "test.png"}`
    jsonMetadata.Set("Content-Type", "application/json")
    part, _ := writer.CreatePart(jsonMetadata)
    part.Write([]byte(metadata))

    // Image bytes (part-2)
    imageData := textproto.MIMEHeader{}
    partAttach, _ := writer.CreatePart(imageData)
    io.Copy(partAttach, bytes.NewReader(mediaData))
    writer.Close()

    // Request Content Type with boundary
    contentType := fmt.Sprintf("multipart/related; boundary=%s", writer.Boundary())

    // HTTP Request with auth and content type headers
    req, _ := http.NewRequest(http.MethodPost, "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart", bytes.NewReader(body.Bytes()))
    req.Header.Add("Authorization", "Bearer "+accessToken)
    req.Header.Add("Content-Type", contentType)

    // Send request
    resp, err := client.Do(req)
    if err != nil {
        log.Fatalf("failed to send request: %v", err)
    }
    defer resp.Body.Close()
    content, _ := ioutil.ReadAll(resp.Body)

    log.Printf("http status: %d", resp.StatusCode)
    log.Printf("response: %s", string(content))
}

Reference: https://developers.google.com/drive/api/v3/manage-uploads?authuser=1#send_a_multipart_upload_request