Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
217 changes: 179 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 intialize Cloudinary, %v", err)
log.Fatalf("failed to initialize Cloudinary: %v", err)
}
ctx := context.Background()

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".
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 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 (first 5 per page)
listAssetsWithPagination(cld, ctx, 5)
}

// 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,97 @@ 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,e_volume:0.5,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 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 := ""

for {
Comment thread
arya2004 marked this conversation as resolved.
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
}
}