app.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. // Copyright 2014 Google Inc. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. //[START sample]
  15. // Package gcsdemo is an example App Engine app using the Google Cloud Storage API.
  16. package gcsdemo
  17. //[START imports]
  18. import (
  19. "bytes"
  20. "fmt"
  21. "io"
  22. "io/ioutil"
  23. "net/http"
  24. "strings"
  25. "golang.org/x/net/context"
  26. "google.golang.org/appengine"
  27. "google.golang.org/appengine/file"
  28. "google.golang.org/appengine/log"
  29. "google.golang.org/cloud/storage"
  30. )
  31. //[END imports]
  32. // bucket is a local cache of the app's default bucket name.
  33. var bucket string // or: var bucket = "<your-app-id>.appspot.com"
  34. func init() {
  35. http.HandleFunc("/", handler)
  36. }
  37. // demo struct holds information needed to run the various demo functions.
  38. type demo struct {
  39. bucket *storage.BucketHandle
  40. client *storage.Client
  41. w http.ResponseWriter
  42. ctx context.Context
  43. // cleanUp is a list of filenames that need cleaning up at the end of the demo.
  44. cleanUp []string
  45. // failed indicates that one or more of the demo steps failed.
  46. failed bool
  47. }
  48. func (d *demo) errorf(format string, args ...interface{}) {
  49. d.failed = true
  50. log.Errorf(d.ctx, format, args...)
  51. }
  52. // handler is the main demo entry point that calls the GCS operations.
  53. func handler(w http.ResponseWriter, r *http.Request) {
  54. if r.URL.Path != "/" {
  55. http.NotFound(w, r)
  56. return
  57. }
  58. ctx := appengine.NewContext(r)
  59. if bucket == "" {
  60. var err error
  61. if bucket, err = file.DefaultBucketName(ctx); err != nil {
  62. log.Errorf(ctx, "failed to get default GCS bucket name: %v", err)
  63. return
  64. }
  65. }
  66. client, err := storage.NewClient(ctx)
  67. if err != nil {
  68. log.Errorf(ctx, "failed to get default GCS bucket name: %v", err)
  69. return
  70. }
  71. defer client.Close()
  72. w.Header().Set("Content-Type", "text/plain; charset=utf-8")
  73. fmt.Fprintf(w, "Demo GCS Application running from Version: %v\n", appengine.VersionID(ctx))
  74. fmt.Fprintf(w, "Using bucket name: %v\n\n", bucket)
  75. d := &demo{
  76. w: w,
  77. ctx: ctx,
  78. client: client,
  79. bucket: client.Bucket(bucket),
  80. }
  81. n := "demo-testfile-go"
  82. d.createFile(n)
  83. d.readFile(n)
  84. d.copyFile(n)
  85. d.statFile(n)
  86. d.createListFiles()
  87. d.listBucket()
  88. d.listBucketDirMode()
  89. d.defaultACL()
  90. d.putDefaultACLRule()
  91. d.deleteDefaultACLRule()
  92. d.bucketACL()
  93. d.putBucketACLRule()
  94. d.deleteBucketACLRule()
  95. d.acl(n)
  96. d.putACLRule(n)
  97. d.deleteACLRule(n)
  98. d.deleteFiles()
  99. if d.failed {
  100. io.WriteString(w, "\nDemo failed.\n")
  101. } else {
  102. io.WriteString(w, "\nDemo succeeded.\n")
  103. }
  104. }
  105. //[START write]
  106. // createFile creates a file in Google Cloud Storage.
  107. func (d *demo) createFile(fileName string) {
  108. fmt.Fprintf(d.w, "Creating file /%v/%v\n", bucket, fileName)
  109. wc := d.bucket.Object(fileName).NewWriter(d.ctx)
  110. wc.ContentType = "text/plain"
  111. wc.Metadata = map[string]string{
  112. "x-goog-meta-foo": "foo",
  113. "x-goog-meta-bar": "bar",
  114. }
  115. d.cleanUp = append(d.cleanUp, fileName)
  116. if _, err := wc.Write([]byte("abcde\n")); err != nil {
  117. d.errorf("createFile: unable to write data to bucket %q, file %q: %v", bucket, fileName, err)
  118. return
  119. }
  120. if _, err := wc.Write([]byte(strings.Repeat("f", 1024*4) + "\n")); err != nil {
  121. d.errorf("createFile: unable to write data to bucket %q, file %q: %v", bucket, fileName, err)
  122. return
  123. }
  124. if err := wc.Close(); err != nil {
  125. d.errorf("createFile: unable to close bucket %q, file %q: %v", bucket, fileName, err)
  126. return
  127. }
  128. }
  129. //[END write]
  130. //[START read]
  131. // readFile reads the named file in Google Cloud Storage.
  132. func (d *demo) readFile(fileName string) {
  133. io.WriteString(d.w, "\nAbbreviated file content (first line and last 1K):\n")
  134. rc, err := d.bucket.Object(fileName).NewReader(d.ctx)
  135. if err != nil {
  136. d.errorf("readFile: unable to open file from bucket %q, file %q: %v", bucket, fileName, err)
  137. return
  138. }
  139. defer rc.Close()
  140. slurp, err := ioutil.ReadAll(rc)
  141. if err != nil {
  142. d.errorf("readFile: unable to read data from bucket %q, file %q: %v", bucket, fileName, err)
  143. return
  144. }
  145. fmt.Fprintf(d.w, "%s\n", bytes.SplitN(slurp, []byte("\n"), 2)[0])
  146. if len(slurp) > 1024 {
  147. fmt.Fprintf(d.w, "...%s\n", slurp[len(slurp)-1024:])
  148. } else {
  149. fmt.Fprintf(d.w, "%s\n", slurp)
  150. }
  151. }
  152. //[END read]
  153. // copyFile copies a file in Google Cloud Storage.
  154. func (d *demo) copyFile(fileName string) {
  155. copyName := fileName + "-copy"
  156. fmt.Fprintf(d.w, "Copying file /%v/%v to /%v/%v:\n", bucket, fileName, bucket, copyName)
  157. obj, err := d.client.CopyObject(d.ctx, bucket, fileName, bucket, copyName, nil)
  158. if err != nil {
  159. d.errorf("copyFile: unable to copy /%v/%v to bucket %q, file %q: %v", bucket, fileName, bucket, copyName, err)
  160. return
  161. }
  162. d.cleanUp = append(d.cleanUp, copyName)
  163. d.dumpStats(obj)
  164. }
  165. func (d *demo) dumpStats(obj *storage.ObjectAttrs) {
  166. fmt.Fprintf(d.w, "(filename: /%v/%v, ", obj.Bucket, obj.Name)
  167. fmt.Fprintf(d.w, "ContentType: %q, ", obj.ContentType)
  168. fmt.Fprintf(d.w, "ACL: %#v, ", obj.ACL)
  169. fmt.Fprintf(d.w, "Owner: %v, ", obj.Owner)
  170. fmt.Fprintf(d.w, "ContentEncoding: %q, ", obj.ContentEncoding)
  171. fmt.Fprintf(d.w, "Size: %v, ", obj.Size)
  172. fmt.Fprintf(d.w, "MD5: %q, ", obj.MD5)
  173. fmt.Fprintf(d.w, "CRC32C: %q, ", obj.CRC32C)
  174. fmt.Fprintf(d.w, "Metadata: %#v, ", obj.Metadata)
  175. fmt.Fprintf(d.w, "MediaLink: %q, ", obj.MediaLink)
  176. fmt.Fprintf(d.w, "StorageClass: %q, ", obj.StorageClass)
  177. if !obj.Deleted.IsZero() {
  178. fmt.Fprintf(d.w, "Deleted: %v, ", obj.Deleted)
  179. }
  180. fmt.Fprintf(d.w, "Updated: %v)\n", obj.Updated)
  181. }
  182. // statFile reads the stats of the named file in Google Cloud Storage.
  183. func (d *demo) statFile(fileName string) {
  184. io.WriteString(d.w, "\nFile stat:\n")
  185. obj, err := d.bucket.Object(fileName).Attrs(d.ctx)
  186. if err != nil {
  187. d.errorf("statFile: unable to stat file from bucket %q, file %q: %v", bucket, fileName, err)
  188. return
  189. }
  190. d.dumpStats(obj)
  191. }
  192. // createListFiles creates files that will be used by listBucket.
  193. func (d *demo) createListFiles() {
  194. io.WriteString(d.w, "\nCreating more files for listbucket...\n")
  195. for _, n := range []string{"foo1", "foo2", "bar", "bar/1", "bar/2", "boo/"} {
  196. d.createFile(n)
  197. }
  198. }
  199. // listBucket lists the contents of a bucket in Google Cloud Storage.
  200. func (d *demo) listBucket() {
  201. io.WriteString(d.w, "\nListbucket result:\n")
  202. query := &storage.Query{Prefix: "foo"}
  203. for query != nil {
  204. objs, err := d.bucket.List(d.ctx, query)
  205. if err != nil {
  206. d.errorf("listBucket: unable to list bucket %q: %v", bucket, err)
  207. return
  208. }
  209. query = objs.Next
  210. for _, obj := range objs.Results {
  211. d.dumpStats(obj)
  212. }
  213. }
  214. }
  215. func (d *demo) listDir(name, indent string) {
  216. query := &storage.Query{Prefix: name, Delimiter: "/"}
  217. for query != nil {
  218. objs, err := d.bucket.List(d.ctx, query)
  219. if err != nil {
  220. d.errorf("listBucketDirMode: unable to list bucket %q: %v", bucket, err)
  221. return
  222. }
  223. query = objs.Next
  224. for _, obj := range objs.Results {
  225. fmt.Fprint(d.w, indent)
  226. d.dumpStats(obj)
  227. }
  228. for _, dir := range objs.Prefixes {
  229. fmt.Fprintf(d.w, "%v(directory: /%v/%v)\n", indent, bucket, dir)
  230. d.listDir(dir, indent+" ")
  231. }
  232. }
  233. }
  234. // listBucketDirMode lists the contents of a bucket in dir mode in Google Cloud Storage.
  235. func (d *demo) listBucketDirMode() {
  236. io.WriteString(d.w, "\nListbucket directory mode result:\n")
  237. d.listDir("b", "")
  238. }
  239. // dumpDefaultACL prints out the default object ACL for this bucket.
  240. func (d *demo) dumpDefaultACL() {
  241. acl, err := d.bucket.ACL().List(d.ctx)
  242. if err != nil {
  243. d.errorf("defaultACL: unable to list default object ACL for bucket %q: %v", bucket, err)
  244. return
  245. }
  246. for _, v := range acl {
  247. fmt.Fprintf(d.w, "Scope: %q, Permission: %q\n", v.Entity, v.Role)
  248. }
  249. }
  250. // defaultACL displays the default object ACL for this bucket.
  251. func (d *demo) defaultACL() {
  252. io.WriteString(d.w, "\nDefault object ACL:\n")
  253. d.dumpDefaultACL()
  254. }
  255. // putDefaultACLRule adds the "allUsers" default object ACL rule for this bucket.
  256. func (d *demo) putDefaultACLRule() {
  257. io.WriteString(d.w, "\nPut Default object ACL Rule:\n")
  258. err := d.bucket.DefaultObjectACL().Set(d.ctx, storage.AllUsers, storage.RoleReader)
  259. if err != nil {
  260. d.errorf("putDefaultACLRule: unable to save default object ACL rule for bucket %q: %v", bucket, err)
  261. return
  262. }
  263. d.dumpDefaultACL()
  264. }
  265. // deleteDefaultACLRule deleted the "allUsers" default object ACL rule for this bucket.
  266. func (d *demo) deleteDefaultACLRule() {
  267. io.WriteString(d.w, "\nDelete Default object ACL Rule:\n")
  268. err := d.bucket.DefaultObjectACL().Delete(d.ctx, storage.AllUsers)
  269. if err != nil {
  270. d.errorf("deleteDefaultACLRule: unable to delete default object ACL rule for bucket %q: %v", bucket, err)
  271. return
  272. }
  273. d.dumpDefaultACL()
  274. }
  275. // dumpBucketACL prints out the bucket ACL.
  276. func (d *demo) dumpBucketACL() {
  277. acl, err := d.bucket.ACL().List(d.ctx)
  278. if err != nil {
  279. d.errorf("dumpBucketACL: unable to list bucket ACL for bucket %q: %v", bucket, err)
  280. return
  281. }
  282. for _, v := range acl {
  283. fmt.Fprintf(d.w, "Scope: %q, Permission: %q\n", v.Entity, v.Role)
  284. }
  285. }
  286. // bucketACL displays the bucket ACL for this bucket.
  287. func (d *demo) bucketACL() {
  288. io.WriteString(d.w, "\nBucket ACL:\n")
  289. d.dumpBucketACL()
  290. }
  291. // putBucketACLRule adds the "allUsers" bucket ACL rule for this bucket.
  292. func (d *demo) putBucketACLRule() {
  293. io.WriteString(d.w, "\nPut Bucket ACL Rule:\n")
  294. err := d.bucket.ACL().Set(d.ctx, storage.AllUsers, storage.RoleReader)
  295. if err != nil {
  296. d.errorf("putBucketACLRule: unable to save bucket ACL rule for bucket %q: %v", bucket, err)
  297. return
  298. }
  299. d.dumpBucketACL()
  300. }
  301. // deleteBucketACLRule deleted the "allUsers" bucket ACL rule for this bucket.
  302. func (d *demo) deleteBucketACLRule() {
  303. io.WriteString(d.w, "\nDelete Bucket ACL Rule:\n")
  304. err := d.bucket.ACL().Delete(d.ctx, storage.AllUsers)
  305. if err != nil {
  306. d.errorf("deleteBucketACLRule: unable to delete bucket ACL rule for bucket %q: %v", bucket, err)
  307. return
  308. }
  309. d.dumpBucketACL()
  310. }
  311. // dumpACL prints out the ACL of the named file.
  312. func (d *demo) dumpACL(fileName string) {
  313. acl, err := d.bucket.Object(fileName).ACL().List(d.ctx)
  314. if err != nil {
  315. d.errorf("dumpACL: unable to list file ACL for bucket %q, file %q: %v", bucket, fileName, err)
  316. return
  317. }
  318. for _, v := range acl {
  319. fmt.Fprintf(d.w, "Scope: %q, Permission: %q\n", v.Entity, v.Role)
  320. }
  321. }
  322. // acl displays the ACL for the named file.
  323. func (d *demo) acl(fileName string) {
  324. fmt.Fprintf(d.w, "\nACL for file %v:\n", fileName)
  325. d.dumpACL(fileName)
  326. }
  327. // putACLRule adds the "allUsers" ACL rule for the named file.
  328. func (d *demo) putACLRule(fileName string) {
  329. fmt.Fprintf(d.w, "\nPut ACL rule for file %v:\n", fileName)
  330. err := d.bucket.Object(fileName).ACL().Set(d.ctx, storage.AllUsers, storage.RoleReader)
  331. if err != nil {
  332. d.errorf("putACLRule: unable to save ACL rule for bucket %q, file %q: %v", bucket, fileName, err)
  333. return
  334. }
  335. d.dumpACL(fileName)
  336. }
  337. // deleteACLRule deleted the "allUsers" ACL rule for the named file.
  338. func (d *demo) deleteACLRule(fileName string) {
  339. fmt.Fprintf(d.w, "\nDelete ACL rule for file %v:\n", fileName)
  340. err := d.bucket.Object(fileName).ACL().Delete(d.ctx, storage.AllUsers)
  341. if err != nil {
  342. d.errorf("deleteACLRule: unable to delete ACL rule for bucket %q, file %q: %v", bucket, fileName, err)
  343. return
  344. }
  345. d.dumpACL(fileName)
  346. }
  347. // deleteFiles deletes all the temporary files from a bucket created by this demo.
  348. func (d *demo) deleteFiles() {
  349. io.WriteString(d.w, "\nDeleting files...\n")
  350. for _, v := range d.cleanUp {
  351. fmt.Fprintf(d.w, "Deleting file %v\n", v)
  352. if err := d.bucket.Object(v).Delete(d.ctx); err != nil {
  353. d.errorf("deleteFiles: unable to delete bucket %q, file %q: %v", bucket, v, err)
  354. return
  355. }
  356. }
  357. }
  358. //[END sample]