Self-Hosted Image Upload and Resize Script in Go

Recently I researched solutions for image upload and resizing, and I’ve looked at a few open source solutions and settled for this one: picfit.

It’s written in Go, it’s simple to set up and use, and it has S3 support out of the box.

The official introduction tutorial is here. However, I’m going to outline my steps here as well since I installed it on my Digital Ocean droplet differently than it’s written in the tutorial.

Installation

I’m using DigitalOcean for all my testing. If you signup using this link you’ll get 10$ which will be enough to run a test ‘droplet’ for two months.

My Droplet runs on Ubuntu, so I installed it by following the official Digital Ocean tutorial:

Install Go

sudo apt-get update
sudo apt-get -y upgrade
sudo curl -O https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz
sudo tar -xvf go1.8.linux-amd64.tar.gz
sudo mv go /usr/local

Add Go to the PATH variable

Aappend this line to the ~/.profile file:

export PATH=$PATH:/usr/local/go/bin

Enable terminal to pull new settings

source ~/.profile

Download picfit

  • Create new folder for Go programs: mkdir $HOME/work
  • Set the path to it in the GOPATH variable: export GOPATH=$HOME/work
  • Get picfit via go: go get github.com/thoas/picfit
  • Make a build:
cd ~/work/src/github.com/thoas/picfit
make build
cd bin

Set the configuration

Create the config.json file inside the bin folder:

{
  "port": 3117,
  "storage": {
    "src": {
      "type": "fs",
      "location": "/home/nikola/work/src/github.com/thoas/picfit/bin"
    }
  },
  "kvstore": {
    "type": "cache"
  }
}

Run it

Finally, run picfit with: ./picfit -c config.json

If everything goes fine you should see an output like this:

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:    export GIN_MODE=release
 - using code:    gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /stats                    --> github.com/thoas/picfit/server.Router.func2 (10 handlers)
[GIN-debug] GET    /redirect                 --> github.com/thoas/picfit/views.RedirectView (16 handlers)
[GIN-debug] GET    /redirect/*parameters     --> github.com/thoas/picfit/views.RedirectView (16 handlers)
[GIN-debug] GET    /display                  --> github.com/thoas/picfit/views.DisplayView (16 handlers)
[GIN-debug] GET    /display/*parameters      --> github.com/thoas/picfit/views.DisplayView (16 handlers)
[GIN-debug] GET    /get                      --> github.com/thoas/picfit/views.GetView (16 handlers)
[GIN-debug] GET    /get/*parameters          --> github.com/thoas/picfit/views.GetView (16 handlers)
[GIN-debug] Listening and serving HTTP on :3117

Usage

Copied from the official tutorial:

http://localhost:3117/{method}?url={url}&path={path}&w={width}&h={height}&upscale={upscale}&sig={sig}&op={operation}&fmt={format}

  • path – file path to load the image using your source storage (optional, if you haven’t configured a source storage)
  • method – operation to perform: display, redirect or get
  • sig – signature key which is the representation of your query string and your secret key (optional, if you haven’t configured a secret key)
  • url – url of the image which will be retrieved by HTTP (optional, if path is provided)
  • width – desired width of the image, if 0 is provided the service will calculate the ratio with height
  • height – desired height of the image, if 0 is provided the service will calculate the ratio with width
    upscale — If your image is smaller than your desired dimensions, the service will upscale it by default to fit your dimensions, you can disable this behavior by providing 0 (optional)
  • format – output format to save the image, by default the format will be the source format, for example, a GIF image source will be saved as GIF (optional)

Examples

The links are for your localhost (change to your IP if you’ll be testing this somewhere else):

Conclusion

Sure, this solution doesn’t have all the bells and whistles that you may want. But, the awesome thing is that it can extend to your liking.

For example, if you want to add some watermark to a particular image, you could do that (of course, given that you know Go. If not, there are some other solutions for other languages like for example this one for PHP.

If you don’t like messing with your solution, I would recommend you check out Cloudinary (cloudinary.com). It’s a paid solution, but it even has a free tier which you can use for testing, and it has some really advanced image manipulation features.

Do you maybe have some other to recommend?

Written by Nikola Brežnjak