Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rootsongjc committed Oct 29, 2017
0 parents commit 455c1e6
Show file tree
Hide file tree
Showing 11 changed files with 1,865 additions and 0 deletions.
133 changes: 133 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
Cloudinary-go
=============

A Go client library and CLI tool to upload static assets to the [Cloudinary](http://www.cloudinary.com) service.

Installation
------------

Install the CLI tool and the library with:

```Bash
go get github.com/rootsongjc/cloudinary-go/cloudinary
```

## Configuration

Create a default configuration file named `${HOME}/.cloudinary.toml`

```toml
[cloudinary]
uri=cloudinary://api_key:api_secret@cloud_name # check your cloudinary dashboard to the the uri
prepend = "images" # default cloudinary folder
```

Usage
-----


```bash
A CLI tool to upload static assets to the Cloudinary service.

Usage:
cloudinary [command]

Available Commands:
help Help about any command
ls list files
put Upload file
rm Remove file

Flags:
--config string config file (default is $HOME/.cloudinary.toml)
-h, --help help for cloudinary
-i, --image string image filename or public id
-p, --path string flle prepend path
-r, --raw string raw filename or public id
-s, --simulate simulate, do nothing (dry run)
-v, --verbose verbose output

Use "cloudinary [command] --help" for more information about a command.
```

Type ``cloudinary`` in the terminal to get some help.

### Upload

```bash
# upload image file
cloudinary put -i abc.jpg -p images
# upload raw file
cloudinary put -r abc.js -p js
```

As the local image uploaded to cloudinary, you will get a URL such like this:

```bash
cloudinary put -i cover.jpg
Using config file: /Users/jimmy/.cloudinary.toml
Warning: database not set (upload sync disabled)
Default remote prepend path set to: images/
==> PublicID: images/cover
==> Uploading as images
2017/10/29 14:49:01 Uploading: cover.jpg
2017/10/29 14:49:06 URL: https://res.cloudinary.com/jimmysong/image/upload/images/cover.jpg
```

The URL `https://res.cloudinary.com/jimmysong/image/upload/images/cover.jpg` represent the laster version of the image.

You can use `ls` to get the upload version.

### List

```bash
# list all resources
cloudinary ls
# list specified static file details
cloudinary ls -i abc -p images
```

List raw file details not support.

Get the upload version.

```bash
cloudinary ls -i cover.jpg
Using config file: /Users/jimmy/.cloudinary.toml
Warning: database not set (upload sync disabled)
Default remote prepend path set to: images/
==> PublicID: images/cover
==> Image Details:
public_id Format Version Type Size(KB) Width Height Url
images/cover jpg 1509259745 image 297 1800 2360 http://res.cloudinary.com/jimmysong/image/upload/v1509259745/images/cover.jpg
```

**Note**: Whether You can specify the file name with extension name or not, that also works.

### Delete

```bash
# delete image
cloudinary delete -i abc -p images
# delete raw resource
cloudinary delete -r abc.js -p js
```

## Note

1. Cloudinary prepend path should not start with a "/" root path

### PublicID

1. PublicID of **Image resource** doesn't include their extension name
2. PublicID of **Raw resource** include their extension name
3. PublicID includes the prepend path

**PublicID example**

| Local file | Prepend path | PublicID |
| ---------- | ------------ | ---------- |
| abc.jpg | images | images/abc |
| abc.js | js | js/abc.js |

More information see [Cloudinary Image upload API reference](https://cloudinary.com/documentation/image_upload_api_reference)
150 changes: 150 additions & 0 deletions admin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Copyright 2013 Mathias Monnerville and Anthony Baillard.
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cloudinary

import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
)

const (
baseAdminUrl = "https://api.cloudinary.com/v1_1"
)

const (
pathListAllImages = "/resources/image"
pathListAllRaws = "/resources/raw"
pathListSingleImage = "/resources/image/upload/"
pathListAllVideos = "/resources/video"
)

const (
maxResults = 2048
)

func (s *Service) dropAllResources(rtype ResourceType, w io.Writer) error {
qs := url.Values{
"max_results": []string{strconv.FormatInt(maxResults, 10)},
}
path := pathListAllImages
if rtype == RawType {
path = pathListAllRaws
}
for {
resp, err := http.Get(fmt.Sprintf("%s%s?%s", s.adminURI, path, qs.Encode()))
m, err := handleHttpResponse(resp)
if err != nil {
return err
}
for _, v := range m["resources"].([]interface{}) {
publicId := v.(map[string]interface{})["public_id"].(string)
if w != nil {
fmt.Fprintf(w, "Deleting %s ... ", publicId)
}
if err := s.Delete(publicId, "", rtype); err != nil {
// Do not return. Report the error but continue through the list.
fmt.Fprintf(w, "Error: %s: %s\n", publicId, err.Error())
}
}
if e, ok := m["next_cursor"]; ok {
qs.Set("next_cursor", e.(string))
} else {
break
}
}

return nil
}

// DropAllImages deletes all remote images from Cloudinary. File names are
// written to io.Writer if available.
func (s *Service) DropAllImages(w io.Writer) error {
return s.dropAllResources(ImageType, w)
}

// DropAllRaws deletes all remote raw files from Cloudinary. File names are
// written to io.Writer if available.
func (s *Service) DropAllRaws(w io.Writer) error {
return s.dropAllResources(RawType, w)
}

// DropAll deletes all remote resources (both images and raw files) from Cloudinary.
// File names are written to io.Writer if available.
func (s *Service) DropAll(w io.Writer) error {
if err := s.DropAllImages(w); err != nil {
return err
}
if err := s.DropAllRaws(w); err != nil {
return err
}
return nil
}

func (s *Service) doGetResources(rtype ResourceType) ([]*Resource, error) {
qs := url.Values{
"max_results": []string{strconv.FormatInt(maxResults, 10)},
}
path := pathListAllImages
if rtype == RawType {
path = pathListAllRaws
} else if rtype == VideoType {
path = pathListAllVideos
}
allres := make([]*Resource, 0)
for {
resp, err := http.Get(fmt.Sprintf("%s%s?%s", s.adminURI, path, qs.Encode()))
if err != nil {
return nil, err
}

rs := new(resourceList)
dec := json.NewDecoder(resp.Body)
if err := dec.Decode(rs); err != nil {
return nil, err
}
for _, res := range rs.Resources {
allres = append(allres, res)
}
if rs.NextCursor > 0 {
qs.Set("next_cursor", strconv.FormatInt(rs.NextCursor, 10))
} else {
break
}
}
return allres, nil
}

func (s *Service) doGetResourceDetails(publicId string) (*ResourceDetails, error) {
path := pathListSingleImage

resp, err := http.Get(fmt.Sprintf("%s%s%s", s.adminURI, path, publicId))
if err != nil {
return nil, err
}
details := new(ResourceDetails)
dec := json.NewDecoder(resp.Body)
if err := dec.Decode(details); err != nil {
return nil, err
}
return details, nil
}

// Resources returns a list of all uploaded resources. They can be
// images or raw files, depending on the resource type passed in rtype.
// Cloudinary can return a limited set of results. Pagination is supported,
// so the full set of results is returned.
func (s *Service) Resources(rtype ResourceType) ([]*Resource, error) {
return s.doGetResources(rtype)
}

// GetResourceDetails gets the details of a single resource that is specified by publicId.
func (s *Service) ResourceDetails(publicId string) (*ResourceDetails, error) {
return s.doGetResourceDetails(publicId)
}
Loading

0 comments on commit 455c1e6

Please sign in to comment.