Search code examples
imagegoserveruploadimagekit

Upload Image to imagekit using Golang (Gin)


I trying to make simple server that able to upload image and return the url of image with go.

here is my code

package controlers

import (
    "context"
    "net/http"
    "os"

    "github.com/codedius/imagekit-go"
    "github.com/gin-gonic/gin"
)

func UploadImage(ctx *gin.Context) {
    // Replace with your own API keys
    publicKey := os.Getenv("IMAGEKITPUBLICKEY")
    privateKey := os.Getenv("IMAGEKITPRIVATEKEY")

    opts := imagekit.Options{
        PublicKey:  publicKey,
        PrivateKey: privateKey,
    }

    // Create a new ImageKit client
    client, err := imagekit.NewClient(&opts)
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error": "fail to create client imege",
        })
    }

    // Open the image file to upload
    file, err := os.Open("image.jpg")
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error": "failed to open image file",
        })
        return
    }
    defer file.Close()

    // Upload the image to ImageKit
    uploadParams := imagekit.UploadRequest{
        File:              file,
        FileName:          "image.jpg",
        UseUniqueFileName: false,
        Tags:              []string{"go", "image"},
        Folder:            "/",
        IsPrivateFile:     false,
    }

    c := context.Background()
    uploadResult, err := client.Upload.ServerUpload(c, &uploadParams)
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error": "failed to upload image",
        })
        return
    }
    // Return the URL of the uploaded image as a JSON response
    ctx.JSON(http.StatusOK, gin.H{
        "url": uploadResult.URL,
    })
}

it will be called using this router package

package routers

import (
    "API-Books/controlers"
    
    "github.com/gin-contrib/cors"
    "github.com/gin-gonic/gin"

func StartServer() *gin.Engine {
    router := gin.Default()

    // Enable CORS
    router.Use(func(c *gin.Context) {
        c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
        c.Next()
    })
    config := cors.DefaultConfig()
    config.AllowOrigins = []string{"http://localhost:3000"}
    router.Use(cors.New(config))
        
        // another router
    router.POST("/api/upload", controlers.UploadImage)

    return router
}
)

and run from main function

package main

import (
    "API-Books/routers"
)

func init() {
    initializer.LoadEnvVar()
}

func main() {
    routers.StartServer().Run()
}

I already put image file in same directory with main.go its named "image.jpg"

I want to when I try post a request it will upload image and returned a link (i will store it to database later, or if you have better solution other than imagekit.io I will apreciate (its just school project so please only free service"


Solution

  • Since it's a school project I would say go for Minio storage.

    Either you can download the binary of Minio and run it you will get the URL Endpoint, AccessKey and SecretKey. Or else you can pull the image of Minio and run it in docker.

    From your go code you can easily connect with it by just initializing the client object:-

    import (
        "github.com/minio/minio-go/v7"
    )
        // Initialize minio client object
        minioClient, err := minio.New("s3.example.com", "ACCESS_KEY", "SECRET_KEY", true)
        if err != nil {
            log.Fatalln(err)
        }
    

    You can upload the file with your own specified bucket name like this:-

    // Upload the file to the specified bucket with the specified name
    _, err = minioClient.FPutObject(context.Background(), bucketName, objectName, filePath, minio.PutObjectOptions{})
    if err != nil {
        log.Fatalln(err)
    }
    

    And finally you can get the URL of the uploaded images by using PresignedGetObject() function like below:-

    // Get the URL of the uploaded file
    objectURL, err := minioClient.PresignedGetObject(context.Background(), bucketName, objectName, time.Second*60, nil)
    if err != nil {
        log.Fatalln(err)
    }
    
    fmt.Println("Object URL:", objectURL)
    

    There are multiple functions and methods. You can utilise them by doing the R&D from here:- https://pkg.go.dev/github.com/minio/minio-go/v7