Welcome To Golang By Example

HTTP send/receive jpeg file in request body example in Go (Golang)

Overview

multipart/form-data content-type can be used to send the jpeg files in an HTTP POST call. The form-data will contain

Let’s see an example of both HTTP client and server

HTTP Server

Below is the program for the same.

package main

import (
	"io"
	"net/http"
	"os"
)

func main() {
	createImageHandler := http.HandlerFunc(createImage)
	http.Handle("/image", createImageHandler)
	http.ListenAndServe(":8080", nil)
}

func createImage(w http.ResponseWriter, request *http.Request) {
	err := request.ParseMultipartForm(32 << 20) // maxMemory 32MB
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	//Access the photo key - First Approach
	file, h, err := request.FormFile("photo")
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	tmpfile, err := os.Create("./" + h.Filename)
	defer tmpfile.Close()
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
	_, err = io.Copy(tmpfile, file)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.WriteHeader(200)
	return
}

Let's understand the program also. The first thing we need to do is to call ParseMultipartForm function on the request object

request.ParseMultipartForm()

It will parse the form data request body. After that, we can call the FormFile function on the request object passing the key as an argument. It will return the multipart.File object for the given key which is "photo" here. This object is an interface to access the file part of a multipart message for that key. The program uses it to save the file to the disk.

_, err = io.Copy(tmpfile, file)

This was the HTTP server example. Run the server. It will listen on 8080 port. Let's create an HTTP client to test the above server as well. Below is the code for that.

HTTP Client

package main

import (
	"bytes"
	"io"
	"log"
	"mime/multipart"
	"net/http"
	"os"
	"time"
)

func main() {
	call("http://localhost:8080/image", "POST")
}

func call(urlPath, method string) error {
	client := &http.Client{
		Timeout: time.Second * 10,
	}

	// New multipart writer.
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	fw, err := writer.CreateFormFile("photo", "test.jpg")
	if err != nil {
		return err
	}
	file, err := os.Open("test.jpg")
	if err != nil {
		return err
	}
	_, err = io.Copy(fw, file)
	if err != nil {
		return err
	}
	writer.Close()
	req, err := http.NewRequest(method, urlPath, bytes.NewReader(body.Bytes()))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", writer.FormDataContentType())
	rsp, _ := client.Do(req)
	if rsp.StatusCode != http.StatusOK {
		log.Printf("Request failed with response code: %d", rsp.StatusCode)
	}
	return nil
}

Below is the code for an example of an HTTP client for the same. It is sending the multipart/form-data request body in an HTTP request to the server created in the above example.

First, we have to create a multipart Writer https://golang.org/pkg/mime/multipart/#Writer

writer := multipart.NewWriter(body)

The multipart writer provides the CreateFormFile method which can be used to create a file field to be sent in the multipart request body. The filename is test.jpg and the key name is "photo".Run the above file.

It will send the test.jpg to the server created above. You can check at the server end after the request finishes. The server will parse the form-data request body and then save the file contents to a file with the same name.