/
drive_converter.go
138 lines (120 loc) · 3.25 KB
/
drive_converter.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
130
131
132
133
134
135
136
137
138
package exchange
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"code.google.com/p/google-api-go-client/drive/v2"
"github.com/golang/oauth2"
"github.com/golang/oauth2/google"
)
type ContentType string
const (
ExcelContentType ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
CSVContentType ContentType = "text/csv"
)
type googleDriveFile struct {
*os.File
size int
contentType string
}
func (f googleDriveFile) Len() int {
return f.size
}
func (f googleDriveFile) ContentType() string {
return f.contentType
}
type GoogleDriveConverter struct {
flow *oauth2.Flow
}
// How to create a google api service account: https://developers.google.com/drive/web/service-accounts
// About google-api-go-client: https://code.google.com/p/google-api-go-client/wiki/GettingStarted
//
// 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.
//
// More explanations, see: http://godoc.org/github.com/golang/oauth2
func NewGoogleDriveConverter(clientEmail, keyFilePath string) (gdc *GoogleDriveConverter, err error) {
key, err := ioutil.ReadFile(keyFilePath)
if err != nil {
return
}
gdc = new(GoogleDriveConverter)
gdc.flow, err = oauth2.New(
oauth2.JWTClient(clientEmail, key),
oauth2.Scope("https://www.googleapis.com/auth/drive"),
google.JWTEndpoint(),
// oauth2.Subject("user@example.com"),
)
if err != nil {
return
}
return
}
// NewGoogleDriveConverterByJSONKey will accept a json key file downloaded from google
// project and return a GoogleDriveConverter. Built for convinence.
func NewGoogleDriveConverterByJSONKey(filename string) (gdc *GoogleDriveConverter, err error) {
// rawkey, err := ioutil.ReadFile(jsonKey)
// if err != nil {
// return
// }
// key := map[string]string{}
// err = json.Unmarshal(rawkey, &key)
// if err != nil {
// return
// }
gdc = new(GoogleDriveConverter)
gdc.flow, err = oauth2.New(
google.ServiceAccountJSONKey(filename),
oauth2.Scope("https://www.googleapis.com/auth/drive"),
)
// gdc.config, err = google.NewServiceAccountConfig(&oauth2.JWTOptions{
// Email: key["client_email"],
// PrivateKey: []byte(key["private_key"]),
// Scopes: []string{"https://www.googleapis.com/auth/drive"},
// })
if err != nil {
return
}
return
}
func (gdc *GoogleDriveConverter) Convert(path string, from, to ContentType) (r io.Reader, err error) {
gdf := &googleDriveFile{contentType: string(from)}
gdf.File, err = os.Open(path)
if err != nil {
return
}
stat, err := gdf.File.Stat()
if err != nil {
return
}
gdf.size = int(stat.Size())
client := http.Client{Transport: gdc.flow.NewTransport()}
svc, err := drive.New(&client)
if err != nil {
return
}
scheme := &drive.File{MimeType: string(from)}
file, err := svc.Files.Insert(scheme).Media(gdf).Convert(true).Do()
if err != nil {
return
}
csvLink, ok := file.ExportLinks[string(to)]
if !ok {
err = fmt.Errorf("can't find ExportLinks for %s", string(to))
return
}
resp, err := client.Get(csvLink)
if err != nil {
return
}
r = resp.Body
return
}