如何使用Go脚本在Google云存储中获取我的图片(base64)

How to get my image (base64) in Google-Cloud-Storage with go script

我一直在寻找示例GAE脚本,以获取从PageSpeed Insights的屏幕截图中获取的图像,并使用Kohana / Cache将其保存为json_decode对象到Google Cloud Storage(GCS)。

使用此方法的原因仅是因为我发现此Kohana模型是将文件写入GCS的最便捷方式,尽管我也在寻找其他类似方法,使用Blobstore将文件写入GCS以便在Go API文件时为它们提供服务已弃用,如此处记录。

这是包含屏幕快照图像数据(base64)的存储对象的形式,该图像数据已公开存储在默认应用程序存储区中,对象名称为images / thumb / mythumb.jpg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
stdClass Object
(
    [screenshot] => stdClass Object
        (
            [data] => _9j_4AAQSkZJRgABAQAAAQABAAD_...= // base64 data
            [height] => 240
            [mime_type] => image/jpeg
            [width] => 320
        )

    [otherdata] => Array
        (
            [..] => ..
            [..] => ..
        )

)

我想使用下面的自定义URL将此图像设置为公共图像,以便通过go module进行处理,并且我还需要使其在一定时间内过期,因为我设法定期更新了图像内容本身:

http://myappId.appspot.com/image/thumb/mythumb.jpg

我已在disptach.yaml中进行设置,以将所有图像请求发送到我的go module,如下所示:

1
2
- url:"*/images/*"
  module: go

并在go.yaml中设置处理程序以进行如下图像请求:

1
2
3
4
5
6
handlers:
- url: /images/thumb/.*
  script: _go_app

- url: /images
  static_dir: images

使用此指令,我得到了所有/ images /请求(/ images / thumb / request除外)为静态目录中的图像提供服务,并且/images/thumb/mythumb.jpg进入了模块应用程序。

因此,在名为thumb.go的应用程序文件中,我必须使用什么代码(请参见????),如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package thumb

import(
    //what to import
    ????
    ????
)

const (
    googleAccessID            ="<serviceAccountEmail>@developer.gserviceaccount.com"
    serviceAccountPEMFilename ="YOUR_SERVICE_ACCOUNT_KEY.pem"
    bucket                    ="myappId.appspot.com"
)

var (
    expiration = time.Now().Add(time.Second * 60) //expire in 60 seconds
)

func init() {
    http.HandleFunc("/images/thumb/", handleThumb)
}

func handleThumb(w http.ResponseWriter, r *http.Request) {
    ctx := cloud.NewContext(appengine.AppID(c), hc)
    ???? //what code to get the string of 'mythumb.jpg' from url
    ???? //what code to get the image stored data from GCS
    ???? //what code to encoce base64 data
    w.Header().Set("Content-Type","image/jpeg;")    
    fmt.Fprintf(w,"%v", mythumb.jpg)
}

我从诸如此类或此类的一些示例中获取了许多代码,但到目前为止仍无法完成一项工作。我还尝试了一个与我的案子相近的样本,但是也没有运气。

因此通常,t主要是由于缺少在我用????标记的行上放置正确的代码以及要导入的相关库或路径的原因。如此处和此处所述,我还检查了GCS许可是否丢失了某些内容。

非常感谢您的帮助和建议。


根据您在描述中所读的内容,似乎唯一相关的部分是实际Go代码中的????行。让我知道不是这种情况。

首先????:"用什么代码从URL中获取'mythumb.jpg'的字符串"?

通过阅读代码,您正在寻找从http://localhost/images/thumb/mythumb.jpg之类的URL中提取mythumb.jpg的方法。编写Web应用程序教程中提供了一个工作示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
   "fmt"
   "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w,"Hi there, I love %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

如此

1
http://localhost:8080/monkeys

打印

1
Hi there, I love monkeys!

第二个????:"用什么代码从GCS获取图像存储的数据"?

您可能希望使用的API方法是storage.objects.get。

您确实链接到Google Cloud Storage的JSON API Go示例之一,这是一个很好的常规参考,但与您要解决的问题无关。该特定示例适用于客户端应用程序(因此redirectURL ="urn:ietf:wg:oauth:2.0:oob"行)。此外,此样本使用不建议使用的/过时的oauth2和存储包。

对于要代表自己访问自己的存储桶的应用程序,最干净(且不建议弃用)的一种方法是使用golang / oauth2和Google APIs Go客户端库软件包。

回购中提供了有关如何使用golang / oauth2包通过JSON Web令牌auth进行身份验证的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func ExampleJWTConfig() {
    conf := &jwt.Config{
        Email:"[email protected]",
        // The contents of your RSA private key or your PEM file
        // that contains a private key.
        // If you have a p12 file instead, you
        // can use `openssl` to export the private key into a pem file.
        //
        //    $ openssl pkcs12 -in key.p12 -out key.pem -nodes
        //
        // It only supports PEM containers with no passphrase.
        PrivateKey: []byte("-----BEGIN RSA PRIVATE KEY-----..."),
        Subject:   "[email protected]",
        TokenURL:  "https://provider.com/o/oauth2/token",
    }
    // Initiate an http.Client, the following GET request will be
    // authorized and authenticated on the behalf of [email protected].
    client := conf.Client(oauth2.NoContext)
    client.Get("...")
}

接下来,不要直接使用oauth2 client,而是将该客户端与前面提到的Google API客户端库Go一起使用:

1
2
3
4
service, err := storage.New(client)
if err != nil {
    fatalf(service,"Failed to create service %v", err)
}

是否注意到与过时的JSON API Go示例的相似性?

在处理程序中,您将要出去使用func ObjectsService.Get获取相关对象。假设您知道objectbucket的名称,即

直接从上一个示例开始,您可以使用类似于下面的代码来检索下载链接:

1
2
3
4
5
6
7
if res, err := service.Objects.Get(bucketName, objectName).Do(); err == nil {
    fmt.Printf("The media download link for %v/%v is %v.\
\
", bucketName, res.Name, res.MediaLink)
} else {
    fatalf(service,"Failed to get %s/%s: %s.", bucketName, objectName, err)
}

然后,获取文件,或对文件进行任何操作。完整示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import (
   "golang.org/x/oauth2"
   "golang.org/x/oauth2/jwt"
   "google.golang.org/api/storage/v1"
   "fmt"
)

...

const (
    bucketName ="YOUR_BUCKET_NAME"
    objectName ="mythumb.jpg"
)

func main() {
    conf := &jwt.Config{
        Email:"[email protected]",
        PrivateKey: []byte("-----BEGIN RSA PRIVATE KEY-----..."),
        Subject:   "[email protected]",
        TokenURL:  "https://provider.com/o/oauth2/token",
     }

    client := conf.Client(oauth2.NoContext)

    service, err := storage.New(client)
    if err != nil {
        fatalf(service,"Failed to create service %v", err)
    }

    if res, err := service.Objects.Get(bucketName, objectName).Do(); err == nil {
        fmt.Printf("The media download link for %v/%v is %v.\
\
", bucketName, res.Name, res.MediaLink)
    } else {
        fatalf(service,"Failed to get %s/%s: %s.", bucketName, objectName, err)
    }

    // Go fetch the file, etc.
}

第三????:"编码base64数据的代码是什么"?

使用encoding/base64包非常简单。非常简单,其中包括一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
package main

import (
   "encoding/base64"
   "fmt"
)

func main() {
    data := []byte("any + old & data")
    str := base64.StdEncoding.EncodeToString(data)
    fmt.Println(str)
}

希望有帮助。