-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupload.go
129 lines (100 loc) · 2.85 KB
/
upload.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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package grok
import (
"context"
"encoding/base64"
"fmt"
"io"
"mime/multipart"
"cloud.google.com/go/storage"
"github.com/google/uuid"
)
// UploadKind ...
type UploadKind string
const (
// GoogleStorageURL ...
GoogleStorageURL = "https://storage.googleapis.com/%s/%s"
)
const (
// PublicUpload ...
PublicUpload = "public"
// PrivateUpload ...
PrivateUpload = "private"
)
// UploadProvider ...
type UploadProvider interface {
New(ctx context.Context, filename string, kind UploadKind) io.WriteCloser
FromRequest(ctx context.Context, file *multipart.FileHeader, kind UploadKind) (url string, err error)
FromBase64(ctx context.Context, base64 string, kind UploadKind) (url string, err error)
}
// GCSUploadProvider ...
type GCSUploadProvider struct {
bucketName string
bucket *storage.BucketHandle
}
// NewGCSUploadProvider ...
func NewGCSUploadProvider(client *storage.Client, projectID, bucket string) *GCSUploadProvider {
gcs := new(GCSUploadProvider)
gcs.ensureBucket(client, projectID, bucket)
return gcs
}
// New ...
func (gcs *GCSUploadProvider) New(ctx context.Context, filename string, kind UploadKind) io.WriteCloser {
o := gcs.bucket.Object(filename)
w := o.NewWriter(ctx)
switch kind {
case PublicUpload:
w.ACL = []storage.ACLRule{{Entity: storage.AllUsers, Role: storage.RoleReader}}
case PrivateUpload:
w.ACL = []storage.ACLRule{{Entity: storage.AllAuthenticatedUsers, Role: storage.RoleReader}}
}
return w
}
// FromBase64 ...
func (gcs *GCSUploadProvider) FromBase64(ctx context.Context, value string, kind UploadKind) (url string, err error) {
fileName := uuid.New().String()
writer := gcs.New(ctx, fileName, kind)
data, err := base64.StdEncoding.DecodeString(value)
if err != nil {
return "", err
}
if _, err := writer.Write(data); err != nil {
return "", err
}
if err := writer.Close(); err != nil {
return "", err
}
return gcs.locationURL(fileName), nil
}
// FromRequest ...
func (gcs *GCSUploadProvider) FromRequest(ctx context.Context, file *multipart.FileHeader, kind UploadKind) (string, error) {
writer := gcs.New(ctx, file.Filename, kind)
f, err := file.Open()
if err != nil {
return "", err
}
if _, err := io.Copy(writer, f); err != nil {
return "", err
}
if err := writer.Close(); err != nil {
return "", err
}
return gcs.locationURL(file.Filename), nil
}
func (gcs *GCSUploadProvider) locationURL(filename string) string {
return fmt.Sprintf(GoogleStorageURL, gcs.bucketName, filename)
}
func (gcs *GCSUploadProvider) ensureBucket(client *storage.Client, projectID, bucket string) {
b := client.Bucket(bucket)
if _, err := b.Attrs(context.Background()); err != nil {
if err != storage.ErrBucketNotExist {
panic(err)
}
if err := b.Create(context.Background(), projectID, &storage.BucketAttrs{
Name: bucket,
}); err != nil {
panic(err)
}
}
gcs.bucket = b
gcs.bucketName = bucket
}