// Store binary data to GCS func Store(c context.Context, data []byte, fileName, mimeType, bucketName string) (absFilename string, err error) { if bucketName == "" { var err error if bucketName, err = file.DefaultBucketName(c); err != nil { log.Errorf(c, "failed to get default GCS bucket name: %v", err) return "", err } } client, err := storage.NewClient(c) if err != nil { log.Errorf(c, "failed to create storage client: %v", err) return "", err } defer client.Close() wc := client.Bucket(bucketName).Object(fileName).NewWriter(c) wc.ContentType = mimeType if _, err := wc.Write(data); err != nil { log.Errorf(c, "upload file: unable to write data to bucket %q, file %q: %v", bucketName, fileName, err) return "", err } if err := wc.Close(); err != nil { log.Errorf(c, "upload file: unable to close bucket %q, file %q: %v", bucketName, fileName, err) return "", err } return getAbsFilename(bucketName, fileName), nil }
// handler is the main demo entry point that calls the GCS operations. func handler(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } c := appengine.NewContext(r) if bucket == "" { var err error if bucket, err = file.DefaultBucketName(c); err != nil { log.Errorf(c, "failed to get default GCS bucket name: %v", err) return } } hc := &http.Client{ Transport: &oauth2.Transport{ Source: google.AppEngineTokenSource(c, storage.ScopeFullControl), // Note that the App Engine urlfetch service has a limit of 10MB uploads and // 32MB downloads. // See https://cloud.google.com/appengine/docs/go/urlfetch/#Go_Quotas_and_limits // for more information. Base: &urlfetch.Transport{Context: c}, }, } ctx := cloud.NewContext(appengine.AppID(c), hc) w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(w, "Demo GCS Application running from Version: %v\n", appengine.VersionID(c)) fmt.Fprintf(w, "Using bucket name: %v\n\n", bucket) d := &demo{ c: c, w: w, ctx: ctx, } n := "demo-testfile-go" d.createFile(n) d.readFile(n) d.copyFile(n) d.statFile(n) d.createListFiles() d.listBucket() d.listBucketDirMode() d.defaultACL() d.putDefaultACLRule() d.deleteDefaultACLRule() d.bucketACL() d.putBucketACLRule() d.deleteBucketACLRule() d.acl(n) d.putACLRule(n) d.deleteACLRule(n) d.deleteFiles() if d.failed { io.WriteString(w, "\nDemo failed.\n") } else { io.WriteString(w, "\nDemo succeeded.\n") } }
func handler(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } ctx := appengine.NewContext(r) if bucket == "" { var err error if bucket, err = file.DefaultBucketName(ctx); err != nil { log.Errorf(ctx, "error", err) return } } client, err := storage.NewClient(ctx) if err != nil { log.Errorf(ctx, "error", err) return } defer client.Close() w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(w, "Demo GCS Application running from Version: %v\n", appengine.VersionID(ctx)) fmt.Fprintf(w, "Using bucket name: %v\n\n", bucket) d := &demo{ w: w, ctx: ctx, client: client, bucket: client.Bucket(bucket), } n := "demo-testfile-go" d.makeF(n) d.rFile(n) d.cFile(n) d.statFile(n) d.createListFiles() d.listBucket() d.listBucketDirMode() d.defaultACL() d.putDefaultACLRule() d.deleteDefaultACLRule() d.bucketACL() d.putBucketACLRule() d.deleteBucketACLRule() d.acl(n) d.putACLRule(n) d.deleteACLRule(n) d.deleteFiles() if d.failed { io.WriteString(w, "\nDemo failed.\n") } else { io.WriteString(w, "\nDemo succeeded.\n") } }
// handler is the main demo entry point that calls the GCS operations. func handler(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } c := appengine.NewContext(r) bucketName, err := file.DefaultBucketName(c) if err != nil { c.Errorf("failed to get default GCS bucket name: %v", err) return } config := google.NewAppEngineConfig(c, storage.ScopeFullControl) ctx := cloud.NewContext(appengine.AppID(c), &http.Client{Transport: config.NewTransport()}) w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(w, "Demo GCS Application running from Version: %v\n", appengine.VersionID(c)) fmt.Fprintf(w, "Using bucket name: %v\n\n", bucketName) d := &demo{ c: c, w: w, ctx: ctx, bucket: bucketName, } n := "demo-testfile-go" d.createFile(n) d.readFile(n) d.copyFile(n) d.statFile(n) d.createListFiles() d.listBucket() d.listBucketDirMode() d.defaultACL() d.putDefaultACLRule() d.deleteDefaultACLRule() d.bucketACL() d.putBucketACLRule() d.deleteBucketACLRule() d.acl(n) d.putACLRule(n) d.deleteACLRule(n) d.deleteFiles() if d.failed { io.WriteString(w, "\nDemo failed.\n") } else { io.WriteString(w, "\nDemo succeeded.\n") } }
func Writer(filename string, r *http.Request) (*storage.Writer, error) { c := appengine.NewContext(r) bucket, err := file.DefaultBucketName(c) if err != nil { log.Errorf(c, "Failed to get default bucket: %v", err) return nil, err } ctx, err := auth(r) if err != nil { log.Errorf(c, "Failed to get context: %v", err) return nil, err } w := storage.NewWriter(ctx, bucket, filename) return w, nil }
func handler(res http.ResponseWriter, req *http.Request) { if req.URL.Path != "/" { http.NotFound(res, req) return } //[START get_default_bucket] ctx := appengine.NewContext(res) if bucket == "" { var err error if bucket, err = file.DefaultBucketName(ctx); err != nil { log.Errorf(ctx, "failed to get default GCS bucket name: %v", err) return } } //[END get_default_bucket] //Make Client client, err := storage.NewClient(ctx) if err != nil { log.Errorf(ctx, "failed to get default GCS bucket name: %v", err) return } defer client.Close() //Construct our object to interface with the cloud storage. res.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(res, "Demo GCS Application running from Version: %v\n", appengine.VersionID(ctx)) fmt.Fprintf(res, "Using bucket name: %v\n\n", bucket) d := &demo{ w: res, //The response writer so it knows what to write to later if retrieving. ctx: ctx, //Current Context client: client, //Current Client bucket: client.Bucket(bucket), //Relevant Bucket, bucket is a global string that contains the default bucket location. } //The name of the file we will be creating. n := "demo-testfile-go" //Create the File and store in google cloud. d.createFile(n) d.listBucket() }
// handleListBucket lists the contents of the default bucket func handleListBucket(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) if bucket == "" { var err error if bucket, err = file.DefaultBucketName(ctx); err != nil { log.Errorf(ctx, "failed to get default GCS bucket name: %v", err) return } } client, err := storage.NewClient(ctx) if err != nil { log.Errorf(ctx, "failed to get default GCS bucket name: %v", err) return } defer client.Close() w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(w, "Demo GCS Application running from Version: %v\n", appengine.VersionID(ctx)) fmt.Fprintf(w, "Using bucket name: %v\n\n", bucket) writer := client.Bucket(bucket).Object("foo").NewWriter(ctx) _, err = writer.Write([]byte("Yoho!")) if err != nil { log.Errorf(ctx, "Error while creating file") } log.Infof(ctx, "Created a new file. So yay!") reader, err := client.Bucket(bucket).Object("foo").NewReader(ctx) if err != nil { log.Errorf(ctx, "Error creating reader for object from Bucket. %s", err) } content, err := ioutil.ReadAll(reader) if err != nil { log.Errorf(ctx, "Error reading object") } fmt.Fprintf(w, "Got: %s", &content) }
// Delete removes an object by name from the bucket being used. If the object does not // exist and there is nothing to delete, Delete returns with no error. // TODO Delete thumbnail and web view copies too! func Delete(filename string, r *http.Request) error { c := appengine.NewContext(r) bucket, err := file.DefaultBucketName(c) if err != nil { log.Errorf(c, "Failed to get default bucket: %v", err) return err } ctx, err := auth(r) if err != nil { log.Errorf(c, "Failed to get context: %v", err) return err } log.Infof(c, "Attempting to delete file %v from bucket %v.", filename, bucket) // StatObject is used here to check existence before calling DeleteObject. // If the object does not exist, DeleteObject returns an error that is NOT // ErrObjectNotExist, so it seemed more reliable to check with StatObject first... _, err = storage.StatObject(ctx, bucket, filename) if err == storage.ErrObjectNotExist { log.Warningf(c, "Object does not exist, nothing to delete.") return nil } err = storage.DeleteObject(ctx, bucket, filename) if err != nil { log.Errorf(c, "Failed to delete file.") log.Infof(c, "Attempting to remove public access to file...") aclErr := storage.DeleteACLRule(ctx, bucket, filename, storage.AllUsers) if aclErr != nil { log.Errorf(c, "Failed to remove public file access!") } else { log.Infof(c, "File access removed.") } return err } return nil }
func serveFilesUpload(res http.ResponseWriter, req *http.Request, params httprouter.Params) { serveAPI(res, req, func() interface{} { ctx := appengine.NewContext(req) session, _ := sessionStore.Get(req, "session") _, ok := session.Values["email"].(string) if !ok { return HTTPError{403, "access denied"} } bucket, err := file.DefaultBucketName(ctx) if err != nil { return err } hc := &http.Client{ Transport: &oauth2.Transport{ Source: google.AppEngineTokenSource(ctx, storage.ScopeFullControl), Base: &urlfetch.Transport{Context: ctx}, }, } id := uuid.NewV1().String() ff, _, err := req.FormFile("file") if err != nil { return err } defer ff.Close() cctx := cloud.NewContext(appengine.AppID(ctx), hc) wc := storage.NewWriter(cctx, bucket, id) io.Copy(wc, ff) err = wc.Close() if err != nil { return err } return id }) }
// Files func serveFilesGet(res http.ResponseWriter, req *http.Request, params httprouter.Params) { serveAPI(res, req, func() interface{} { ctx := appengine.NewContext(req) session, _ := sessionStore.Get(req, "session") _, ok := session.Values["email"].(string) if !ok { return HTTPError{403, "access denied"} } bucket, err := file.DefaultBucketName(ctx) if err != nil { return err } hc := &http.Client{ Transport: &oauth2.Transport{ Source: google.AppEngineTokenSource(ctx, storage.ScopeReadOnly), Base: &urlfetch.Transport{Context: ctx}, }, } cctx := cloud.NewContext(appengine.AppID(ctx), hc) rc, err := storage.NewReader(cctx, bucket, params.ByName("id")) if err != nil { return err } name := req.URL.Query().Get("name") if name == "" { name = params.ByName("id") } name = regexp.MustCompile("[^a-zA-Z-_.]").ReplaceAllString(name, "") res.Header().Set("Content-Disposition", "inline; filename=\""+name+"\"") res.Header().Set("Content-Type", "application/octet-stream") return rc }) }
func handler(res http.ResponseWriter, req *http.Request) { if req.URL.Path != "/" { http.NotFound(res, req) return } ctx := appengine.NewContext(res) if bucket == "" { var err error if bucket, err = file.DefaultBucketName(ctx); err != nil { log.Errorf(ctx, "failed to get default GCS bucket name: %v", err) return } } //[END get_default_bucket] //Make Client client, err := storage.NewClient(ctx) if err != nil { log.Errorf(ctx, "failed to get default GCS bucket name: %v", err) return } defer client.Close() res.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(res, "Demo GCS Application running from Version: %v\n", appengine.VersionID(ctx)) fmt.Fprintf(res, "Using bucket name: %v\n\n", bucket) d := &demo{ w: res, ctx: ctx, client: client, bucket: client.Bucket(bucket), } n := "demo-testfile-go" d.createFile(n) d.listBucket() }
// Store binary data to GCS func Store(c context.Context, data []byte, fileName, mimeType, bucketName string) (absFilename string, err error) { if bucketName == "" { var err error if bucketName, err = file.DefaultBucketName(c); err != nil { log.Errorf(c, "failed to get default GCS bucket name: %v", err) return "", err } } hc := &http.Client{ Transport: &oauth2.Transport{ Source: google.AppEngineTokenSource(c, storage.ScopeFullControl), // Note that the App Engine urlfetch service has a limit of 10MB uploads and // 32MB downloads. // See https://cloud.google.com/appengine/docs/go/urlfetch/#Go_Quotas_and_limits // for more information. Base: &urlfetch.Transport{Context: c}, }, } ctx := cloud.NewContext(appengine.AppID(c), hc) wc := storage.NewWriter(ctx, bucketName, fileName) wc.ContentType = mimeType if _, err := wc.Write(data); err != nil { log.Errorf(c, "upload file: unable to write data to bucket %q, file %q: %v", bucketName, fileName, err) return "", err } if err := wc.Close(); err != nil { log.Errorf(c, "upload file: unable to close bucket %q, file %q: %v", bucketName, fileName, err) return "", err } return getAbsFilename(bucketName, fileName), nil }
func Reader(filename string, r *http.Request) (io.ReadCloser, error) { c := appengine.NewContext(r) bucket, err := file.DefaultBucketName(c) if err != nil { log.Errorf(c, "Failed to get default bucket: %v", err) return nil, err } ctx, err := auth(r) if err != nil { log.Errorf(c, "Failed to get context: %v", err) return nil, err } log.Infof(c, "Retrieving file %v from bucket %v.", filename, bucket) rc, err := storage.NewReader(ctx, bucket, filename) if err != nil { log.Errorf(c, "Failed to open file: %v", err) return nil, err } return rc, nil }
func FileStats(filename string, r *http.Request) (*storage.Object, error) { c := appengine.NewContext(r) bucket, err := file.DefaultBucketName(c) if err != nil { log.Errorf(c, "Failed to get default bucket: %v", err) return nil, err } ctx, err := auth(r) if err != nil { log.Errorf(c, "Failed to get context: %v", err) return nil, err } log.Infof(c, "Getting stats for file %v from bucket %v.", filename, bucket) obj, err := storage.StatObject(ctx, bucket, filename) if err != nil { log.Errorf(c, "Failed to stat file: %v", err) return nil, err } return obj, nil }
func storeImage(rw http.ResponseWriter, req *http.Request) { // Appengine var c appengine.Context // Google Cloud Storage authentication var cc gcscontext.Context // Google Cloud Storage bucket name var bucketName string = "" // Google Cloud Storage client var client *storage.Client // Google Cloud Storage bucket var bucketHandle *storage.BucketHandle // User uploaded image file name var fileName string = uuid.New() // Transform user uploaded image to a thumbnail file name var fileNameThumbnail string = uuid.New() // User uploaded image file type var contentType string = "" // User uploaded image file raw data var b []byte // Google Cloud Storage file writer var wc *storage.Writer = nil // Error var err error = nil // Result, 0: success, 1: failed var r int = http.StatusCreated // Set response in the end defer func() { // Return status. WriteHeader() must be called before call to Write if r == http.StatusCreated { // Changing the header after a call to WriteHeader (or Write) has no effect. // rw.Header().Set("Location", req.URL.String()+"/"+cKey.Encode()) rw.Header().Set("Location", "http://"+bucketName+".storage.googleapis.com/"+fileName) rw.Header().Set("X-Thumbnail", "http://"+bucketName+".storage.googleapis.com/"+fileNameThumbnail) rw.WriteHeader(r) } else { http.Error(rw, http.StatusText(r), r) } }() // To log information in Google APP Engine console c = appengine.NewContext(req) // Get data from body b, err = ioutil.ReadAll(req.Body) if err != nil { c.Errorf("%s in reading body", err) r = http.StatusInternalServerError return } c.Infof("Body length %d bytes, read %d bytes", req.ContentLength, len(b)) // Determine filename extension from content type contentType = req.Header["Content-Type"][0] switch contentType { case "image/jpeg": fileName += ".jpg" fileNameThumbnail += ".jpg" default: c.Errorf("Unknown or unsupported content type '%s'. Valid: image/jpeg", contentType) r = http.StatusBadRequest return } c.Infof("Content type %s is received, %s is detected.", contentType, http.DetectContentType(b)) // Prepare Google Cloud Storage authentication cc = gcsappengine.NewContext(req) if client, err = storage.NewClient(cc); err != nil { c.Errorf("%s in initializing a GCS client", err) r = http.StatusInternalServerError return } defer client.Close() // Get default bucket if bucketName, err = gcsfile.DefaultBucketName(cc); err != nil { c.Errorf("%s in getting default GCS bucket name", err) r = http.StatusInternalServerError return } bucketHandle = client.Bucket(bucketName) c.Infof("APP Engine Version: %s", gcsappengine.VersionID(cc)) c.Infof("Using bucket name: %s", bucketName) // Change default object ACLs if err = bucketHandle.DefaultObjectACL().Set(cc, storage.AllUsers, storage.RoleReader); err != nil { c.Errorf("%v in saving default object ACL rule for bucket %q", err, bucketName) r = http.StatusInternalServerError return } // Store rotated image in Google Cloud Storage var in *bytes.Reader = bytes.NewReader(b) var x *exif.Exif = nil var orientation *tiff.Tag = nil var beforeImage image.Image var afterImage *image.NRGBA = nil // Read EXIF if _, err = in.Seek(0, 0); err != nil { c.Errorf("%s in moving the reader offset to the beginning in order to read EXIF", err) return } if x, err = exif.Decode(in); err != nil { c.Errorf("%s in decoding JPEG image", err) return } // Get Orientation if orientation, err = x.Get(exif.Orientation); err != nil { c.Warningf("%s in getting orientation from EXIF", err) return } c.Debugf("Orientation %s", orientation.String()) // Open image if _, err = in.Seek(0, 0); err != nil { c.Errorf("%s in moving the reader offset to the beginning in order to read EXIF", err) return } if beforeImage, err = imaging.Decode(in); err != nil { c.Errorf("%s in opening image %s", err) return } switch orientation.String() { case "1": afterImage = beforeImage.(*image.NRGBA) case "2": afterImage = imaging.FlipH(beforeImage) case "3": afterImage = imaging.Rotate180(beforeImage) case "4": afterImage = imaging.FlipV(beforeImage) case "5": afterImage = imaging.Transverse(beforeImage) case "6": afterImage = imaging.Rotate270(beforeImage) case "7": afterImage = imaging.Transpose(beforeImage) case "8": afterImage = imaging.Rotate90(beforeImage) } // Save rotated image wc = bucketHandle.Object(fileName).NewWriter(cc) wc.ContentType = contentType if err = imaging.Encode(wc, afterImage, imaging.JPEG); err != nil { c.Errorf("%s in saving rotated image", err) return } if err = wc.Close(); err != nil { c.Errorf("CreateFile: unable to close bucket %q, file %q: %v", bucketName, fileName, err) r = 1 return } wc = nil // Make thumbnail if afterImage.Rect.Dx() > afterImage.Rect.Dy() { afterImage = imaging.Resize(afterImage, 1920, 0, imaging.Lanczos) } else { afterImage = imaging.Resize(afterImage, 0, 1920, imaging.Lanczos) } // Save thumbnail wc = bucketHandle.Object(fileNameThumbnail).NewWriter(cc) wc.ContentType = contentType if imaging.Encode(wc, afterImage, imaging.JPEG); err != nil { c.Errorf("%s in saving image thumbnail", err) return } if err = wc.Close(); err != nil { c.Errorf("CreateFileThumbnail: unable to close bucket %q, file %q: %v", bucketName, fileNameThumbnail, err) r = 1 return } c.Infof("/%v/%v, /%v/%v created", bucketName, fileName, bucketName, fileNameThumbnail) }
func storeImage(rw http.ResponseWriter, req *http.Request) { // Appengine var c appengine.Context // Google Cloud Storage authentication var cc gcscontext.Context // Google Cloud Storage bucket name var bucket string = "" // User uploaded image file name var fileName string = uuid.New() // User uploaded image file type var contentType string = "" // User uploaded image file raw data var b []byte // Result, 0: success, 1: failed var r int = 0 // Set response in the end defer func() { // Return status. WriteHeader() must be called before call to Write if r == 0 { // Changing the header after a call to WriteHeader (or Write) has no effect. // rw.Header().Set("Location", req.URL.String()+"/"+cKey.Encode()) rw.Header().Set("Location", "http://"+bucket+".storage.googleapis.com/"+fileName) rw.WriteHeader(http.StatusCreated) } else { http.Error(rw, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) } }() // To log information in Google APP Engine console c = appengine.NewContext(req) // Get data from body b, err := ioutil.ReadAll(req.Body) if err != nil { c.Errorf("%s in reading body", err) r = 1 return } c.Infof("Body length %d bytes, read %d bytes", req.ContentLength, len(b)) // Determine filename extension from content type contentType = req.Header["Content-Type"][0] switch contentType { case "image/jpeg": fileName += ".jpg" default: c.Errorf("Unknown or unsupported content type '%s'. Valid: image/jpeg", contentType) r = 1 return } c.Infof("Content type %s is received, %s is detected.", contentType, http.DetectContentType(b)) // Get default bucket name cc = gcsappengine.NewContext(req) if bucket, err = gcsfile.DefaultBucketName(cc); err != nil { c.Errorf("%s in getting default GCS bucket name", err) r = 1 return } c.Infof("APP Engine Version: %s", gcsappengine.VersionID(cc)) c.Infof("Using bucket name: %s", bucket) // Prepare Google Cloud Storage authentication hc := &http.Client{ Transport: &oauth2.Transport{ Source: google.AppEngineTokenSource(cc, storage.ScopeFullControl), // Note that the App Engine urlfetch service has a limit of 10MB uploads and // 32MB downloads. // See https://cloud.google.com/appengine/docs/go/urlfetch/#Go_Quotas_and_limits // for more information. Base: &gcsurlfetch.Transport{Context: cc}, }, } ctx := cloud.NewContext(gcsappengine.AppID(cc), hc) // Change default object ACLs err = storage.PutDefaultACLRule(ctx, bucket, "allUsers", storage.RoleReader) // err = storage.PutACLRule(ctx, bucket, fileName, "allUsers", storage.RoleReader) if err != nil { c.Errorf("%v in saving ACL rule for bucket %q", err, bucket) return } // Store file in Google Cloud Storage wc := storage.NewWriter(ctx, bucket, fileName) wc.ContentType = contentType // wc.Metadata = map[string]string{ // "x-goog-meta-foo": "foo", // "x-goog-meta-bar": "bar", // } if _, err := wc.Write(b); err != nil { c.Errorf("CreateFile: unable to write data to bucket %q, file %q: %v", bucket, fileName, err) r = 1 return } if err := wc.Close(); err != nil { c.Errorf("CreateFile: unable to close bucket %q, file %q: %v", bucket, fileName, err) r = 1 return } c.Infof("/%v/%v\n created", bucket, fileName) }
// handler is the main demo entry point that calls the GCS operations. func handler(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } //[START get_default_bucket] ctx := appengine.NewContext(r) if bucket == "" { var err error if bucket, err = file.DefaultBucketName(ctx); err != nil { log.Errorf(ctx, "failed to get default GCS bucket name: %v", err) return } } //[END get_default_bucket] client, err := storage.NewClient(ctx) if err != nil { log.Errorf(ctx, "failed to create client: %v", err) return } defer client.Close() w.Header().Set("Content-Type", "text/plain; charset=utf-8") fmt.Fprintf(w, "Demo GCS Application running from Version: %v\n", appengine.VersionID(ctx)) fmt.Fprintf(w, "Using bucket name: %v\n\n", bucket) buf := &bytes.Buffer{} d := &demo{ w: buf, ctx: ctx, client: client, bucket: client.Bucket(bucket), } n := "demo-testfile-go" d.createFile(n) d.readFile(n) d.copyFile(n) d.statFile(n) d.createListFiles() d.listBucket() d.listBucketDirMode() d.defaultACL() d.putDefaultACLRule() d.deleteDefaultACLRule() d.bucketACL() d.putBucketACLRule() d.deleteBucketACLRule() d.acl(n) d.putACLRule(n) d.deleteACLRule(n) d.deleteFiles() if d.failed { w.WriteHeader(http.StatusInternalServerError) buf.WriteTo(w) fmt.Fprintf(w, "\nDemo failed.\n") } else { w.WriteHeader(http.StatusOK) buf.WriteTo(w) fmt.Fprintf(w, "\nDemo succeeded.\n") } }
func Create(filename string, r *http.Request) (*storage.Object, error) { c := appengine.NewContext(r) bucket, err := file.DefaultBucketName(c) if err != nil { log.Errorf(c, "Failed to get default bucket: %v", err) return nil, err } ctx, err := auth(r) if err != nil { log.Errorf(c, "Failed to get context: %v", err) return nil, err } log.Infof(c, "Recieved post with content length %v", r.ContentLength) w := storage.NewWriter(ctx, bucket, filename) file, header, err := r.FormFile("image") if err != nil { log.Errorf(c, "Failed to read form file: %v", err) return nil, err } log.Infof(c, "File Header:\nFilename = %v\nHeader Data = %v", header.Filename, header.Header) sample := make([]byte, 512) read, err := file.Read(sample) if err != nil { log.Warningf(c, "Failed to sniff content type from file sample: %v", err) } else { ct := http.DetectContentType(sample) log.Infof(c, "Sniffed content type: %v", ct) valid := validateContentType(ct) if !valid { log.Warningf(c, "Invalid Content-Type '%v'. Aborting upload.", ct) return nil, errors.New("Invalid file type.") } w.ContentType = ct } log.Infof(c, "Writing %v sample bytes to file.", read) sampleWritten, err := w.Write(sample) if err != nil { log.Errorf(c, "Error during write of file sample bytes. Wrote %v. %v", sampleWritten, err) w.Close() return nil, err } log.Infof(c, "Copying remainder of file...") written, err := io.Copy(w, file) log.Infof(c, "Done. Wrote %v bytes.", written) err = w.Close() if err != nil { log.Errorf(c, "Failed to close writer: %v", err) return nil, err } obj := w.Object() return obj, nil }