Binary Uploads

Sometimes, an API needs to deal with binary files, such as images and PDFs. This article lists and explains the required steps.

We assume the API uses JSON, and that the binary data is sent as a base64-encoded string.

Struct

Create a struct for receiving the upload. Here is an example:

type fileUpload struct {
    Description string `json:"description,omitempty"`
    Base64      string `json:"base64,omitempty"`
    bytes       []byte
}

The bytes field is not exported, and is used to store the decoded base64 data.

Unmarshal

Unmarshal the request body into the struct.

var bu binaryUpload
err := json.Unmarshal(body, &bu)
if err == nil {
    bu.bytes, err = base64.StdEncoding.DecodeString(bu.ImageBase64)
    if err != nil {
        lg.Errorf("failed to base64 decode file: %s", err)
    }
}

Store

The binary file will need to be stored somewhere. The most common practice is to upload it to cloud storage, such as an Amazon S3 bucket. Digital Ocean’s Spaces is an easier to configure, more affordable alternative.

The file can also be saved directly to a database. For example, the bytea field type in PostgreSQL.

Best practices usually preclude storing the binary file to a database, especially when they are large. However, for small documents, depending on the rest of the architecture, it may be a viable option.