Skip to content

Instantly share code, notes, and snippets.

Created December 26, 2020 11:00
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Multipart requests in Go (feat Google Drive API)
package main
import (
func upload() error {
// Metadata content.
metadata := `{"name": "photo-sample.jpeg"}`
// New empty buffer
body := &bytes.Buffer{}
// Creates a new multipart Writer with a random boundary, writing to the empty
// buffer
writer := multipart.NewWriter(body)
// Metadata part
metadataHeader := textproto.MIMEHeader{}
// Set the Content-Type header
metadataHeader.Set("Content-Type", "application/json; charset=UTF-8")
// Create new multipart part
part, err := writer.CreatePart(metadataHeader)
if err != nil {
return err
// Write the part body
// Media part
// Read the file to memory
mediaData, err := ioutil.ReadFile("file.jpeg")
if err != nil {
return err
mediaHeader := textproto.MIMEHeader{}
mediaHeader.Set("Content-Type", "image/jpeg")
mediaPart, err := writer.CreatePart(mediaHeader)
if err != nil {
return err
io.Copy(mediaPart, bytes.NewReader(mediaData))
// Finish the multipart message
accessToken := "<google drive access token>"
endpoint := ""
req, err := http.NewRequest("POST", endpoint, bytes.NewReader(body.Bytes()))
if err != nil {
return err
// Request Content-Type with boundary parameter.
contentType := fmt.Sprintf("multipart/related; boundary=%s", writer.Boundary())
req.Header.Set("Content-Type", contentType)
// Content-Length must be the total number of bytes in the request body.
req.Header.Set("Content-Length", fmt.Sprintf("%d", body.Len()))
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
client := &http.Client{Timeout: 120 * time.Second}
resp, err := client.Do(req)
if err != nil {
return err
defer resp.Body.Close()
// Do what you want with the response
return nil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment