Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CLOUDINARY_URL=cloudinary://<api_key>:<api_secret>@<cloud_name>
25 changes: 25 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work
go.work.sum

# env file
.env
230 changes: 192 additions & 38 deletions example/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,90 +2,137 @@ package main

import (
"context"
"fmt"
"log"
"strings"

"github.com/cloudinary/cloudinary-go/v2"
"github.com/cloudinary/cloudinary-go/v2/api/admin"
"github.com/cloudinary/cloudinary-go/v2/api/admin/search"
"github.com/cloudinary/cloudinary-go/v2/api/uploader"
"log"
)


const (
imageFilePath = "https://res.cloudinary.com/demo/image/upload/sample.jpg"
videoFilePath = "https://res.cloudinary.com/demo/video/upload/dog.mp4"
)

func main() {

// Start by creating a new instance of Cloudinary using CLOUDINARY_URL environment variable.
// Alternatively you can use cloudinary.NewFromParams() or cloudinary.NewFromURL().
var cld, err = cloudinary.New()
cld, err := cloudinary.New()
if err != nil {
log.Fatalf("failed to initialize Cloudinary: %v", err)
}
ctx := context.Background()

uploadResult := uploadImage(cld, ctx)
log.Println(uploadResult.SecureURL)

imageURL := buildImageURL(cld)
log.Printf("Image URL: %s", imageURL)

getAssetDetails(cld, ctx)

searchAssets(cld, ctx)

// Generate responsive srcset for the "logo" image
srcset, err := generateResponsiveSrcSet(cld, "logo")
if err != nil {
log.Fatalf("Failed to intialize Cloudinary, %v", err)
log.Fatalf("failed to build srcset: %v", err)
}
log.Printf("SrcSet: %s", srcset)

// Upload a video with transformations applied on upload
videoResult := uploadVideoWithTransformations(cld, ctx)
log.Println(videoResult.SecureURL)

// Delete a single asset by Public ID
// Note: Once an asset is deleted, the associated URL will no longer work.
// If you want to access the uploaded asset via the logged URL, comment out this deleteAsset() call.
deleteAsset(cld, ctx, "logo")

// Bulk delete multiple assets by Public IDs
// Note: Assets deleted here will also become inaccessible through their URLs.
// Comment out this bulkDeleteAssets() call if you want to keep them available for testing.
bulkDeleteAssets(cld, ctx, []string{"old_img1", "old_img2", "old_img3"})

// List assets with pagination (retrieves up to 2 assets per page)
listAssetsWithPagination(cld, ctx, 2)
}

var ctx = context.Background()

// Upload an image to your Cloudinary account from a specified URL.
//
// Alternatively you can provide a path to a local file on your filesystem,
// base64 encoded string, io.Reader and more.
//
// For additional information see:
// https://cloudinary.com/documentation/upload_images
//
// Upload can be greatly customized by specifying uploader.UploadParams,
// in this case we set the Public ID of the uploaded asset to "logo".
// Upload an image to your Cloudinary account from a specified URL.
//
// Alternatively you can provide a path to a local file on your filesystem,
// base64 encoded string, io.Reader and more.
//
// For additional information see:
// https://cloudinary.com/documentation/upload_images
//
// Upload can be greatly customized by specifying uploader.UploadParams,
// in this case we set the Public ID of the uploaded asset to "logo".
func uploadImage(cld *cloudinary.Cloudinary, ctx context.Context) *uploader.UploadResult {
uploadResult, err := cld.Upload.Upload(
ctx,
"https://cloudinary-res.cloudinary.com/image/upload/cloudinary_logo.png",
uploader.UploadParams{PublicID: "logo"})
imageFilePath,
uploader.UploadParams{PublicID: "logo"},
)
if err != nil {
log.Fatalf("Failed to upload file, %v\n", err)
log.Fatalf("failed to upload file: %v", err)
}

log.Println(uploadResult.SecureURL)
// Prints something like:
// https://res.cloudinary.com/<your cloud name>/image/upload/v1615875158/logo.png

// uploadResult contains useful information about the asset, like Width, Height, Format, etc.
// See uploader.UploadResult struct for more details.
return uploadResult
}

// We can also build an image URL using the Public ID.
// We can also build an image URL using the Public ID.
//
// Image can be further transformed and optimized as follows:
// Here the image is scaled to the width of 500 pixels. Format and quality are set to "auto".
func buildImageURL(cld *cloudinary.Cloudinary) string {
image, err := cld.Image("logo")
if err != nil {
log.Fatalf("Failed to build image URL, %v\n", err)
log.Fatalf("failed to build image URL: %v", err)
}

// Image can be further transformed and optimized as follows:
image.Transformation = "c_scale,w_500/f_auto/q_auto"
// Here the image is scaled to the width of 500 pixes. Format and quality are set to "auto".

imageURL, err := image.String()
if err != nil {
log.Fatalf("Failed to serialize image URL, %v\n", err)
log.Fatalf("failed to serialize image URL: %v", err)
}

log.Printf("Image URL: %s", imageURL)
// Prints something like:
// https://res.cloudinary.com/<your cloud name>/image/upload/c_scale,w_500/f_auto/q_auto/logo
return imageURL
}

// Now we can use Admin API to see the details about the asset.
// The request can be customised by providing AssetParams.
// Now we can use Admin API to see the details about the asset.
// The request can be customised by providing AssetParams.
func getAssetDetails(cld *cloudinary.Cloudinary, ctx context.Context) {
asset, err := cld.Admin.Asset(ctx, admin.AssetParams{PublicID: "logo"})
if err != nil {
log.Fatalf("Failed to get asset details, %v\n", err)
log.Fatalf("failed to get asset details: %v", err)
}

// Print some basic information about the asset.
log.Printf("Public ID: %v, URL: %v\n", asset.PublicID, asset.SecureURL)
}

// Cloudinary also provides a very flexible Search API for filtering and retrieving
// information on all the assets in your account with the help of query expressions
// in a Lucene-like query language.
// Cloudinary also provides a very flexible Search API for filtering and retrieving
// information on all the assets in your account with the help of query expressions
// in a Lucene-like query language.
func searchAssets(cld *cloudinary.Cloudinary, ctx context.Context) {
searchQuery := search.Query{
Expression: "resource_type:image AND uploaded_at>1d AND bytes<1m",
SortBy: []search.SortByField{{"created_at": search.Descending}},
MaxResults: 30,
}

searchResult, err := cld.Admin.Search(ctx, searchQuery)

if err != nil {
log.Fatalf("Failed to search for assets, %v\n", err)
log.Fatalf("failed to search for assets: %v", err)
}

log.Printf("Assets found: %v\n", searchResult.TotalCount)
Expand All @@ -94,3 +141,110 @@ func main() {
log.Printf("Public ID: %v, URL: %v\n", asset.PublicID, asset.SecureURL)
}
}

// Generate a responsive srcset string for a given public ID by building URLs at multiple widths.
func generateResponsiveSrcSet(cld *cloudinary.Cloudinary, publicID string) (string, error) {
widths := []int{200, 400, 800, 1200}
var parts []string

for _, w := range widths {
img, err := cld.Image(publicID)
if err != nil {
return "", fmt.Errorf("failed to initialize image %s: %w", publicID, err)
}
img.Transformation = fmt.Sprintf("c_scale,w_%d/f_auto/q_auto", w)

url, err := img.String()
if err != nil {
return "", fmt.Errorf("failed to build URL for width %d: %w", w, err)
}
parts = append(parts, fmt.Sprintf("%s %dw", url, w))
}

return strings.Join(parts, ", "), nil
}

// Upload a video with transformations applied on upload to generate posters or clips.
func uploadVideoWithTransformations(cld *cloudinary.Cloudinary, ctx context.Context) *uploader.UploadResult {
uploadResult, err := cld.Upload.Upload(
ctx,
videoFilePath,
uploader.UploadParams{
PublicID: "promo_clip",
Folder: "videos/promos",
ResourceType: "video",
Eager: "c_fill,h_360,w_640,b_black|c_crop,ar_16:9,du_15",
Tags: []string{"video", "promo"},
},
)
if err != nil {
log.Fatalf("failed to upload video: %v", err)
}

// uploadResult.SecureURL points to the original video; uploadResult.Eager to derivatives.
return uploadResult
Comment thread
arya2004 marked this conversation as resolved.
}

// Delete a single asset by its Public ID.
func deleteAsset(cld *cloudinary.Cloudinary, ctx context.Context, publicID string) {
_, err := cld.Upload.Destroy(
ctx,
uploader.DestroyParams{PublicID: publicID, ResourceType: "image"},
)
if err != nil {
log.Fatalf("failed to delete asset %s: %v", publicID, err)
}

// Asset deleted successfully.
}

// Bulk delete multiple assets by their Public IDs.
func bulkDeleteAssets(cld *cloudinary.Cloudinary, ctx context.Context, publicIDs []string) {
resp, err := cld.Admin.DeleteAssets(
ctx,
admin.DeleteAssetsParams{PublicIDs: publicIDs},
)
if err != nil {
log.Fatalf("failed to bulk delete assets: %v", err)
}

// Print details of deleted assets.
for publicID, status := range resp.Deleted {
log.Printf("Public ID: %s, Status: %s", publicID, status)
}

// Print how many were deleted.
log.Printf("Deleted assets count: %d", len(resp.Deleted))
Comment thread
arya2004 marked this conversation as resolved.
}

// List all assets in pages of up to maxResults, using cursor-based pagination.
func listAssetsWithPagination(cld *cloudinary.Cloudinary, ctx context.Context, maxResults int) {
nextCursor := ""
loopCount := 0
maxLoops := 2 // Limit the number of loops for demo purposes

for {
Comment thread
arya2004 marked this conversation as resolved.
if loopCount >= maxLoops {
log.Println("Reached maximum number of loops for demo purposes.")
break
}

page, err := cld.Admin.Assets(
ctx,
admin.AssetsParams{MaxResults: maxResults, NextCursor: nextCursor},
)
if err != nil {
log.Fatalf("failed to list assets: %v", err)
}

for _, asset := range page.Assets {
log.Printf("Public ID: %v, URL: %v", asset.PublicID, asset.SecureURL)
}

if page.NextCursor == "" {
break // no more assets
}
nextCursor = page.NextCursor
loopCount++
}
}