func (d *gcsDriver) Create(id string) (driver.WFile, error) { f, _, err := file.Create(d.c, d.path(id), nil) if err != nil { return nil, err } return wfile{f}, nil }
// アップロードされた画像をGCSに保存します。 func Store(c appengine.Context, data []byte, filename, mimeType, bucketName string) (absFilename string, err error) { if len(bucketName) == 0 { bucketName, err = file.DefaultBucketName(c) } if err != nil { c.Errorf("gcs.go:13") return "", err } opts := &file.CreateOptions{ MIMEType: mimeType, BucketName: bucketName, } wc, absFilename, err := file.Create(c, filename, opts) if err != nil { c.Errorf("gcs.go:23") return "", err } defer wc.Close() _, err = wc.Write(data) if err != nil { c.Errorf("gcs.go:30") return "", err } return absFilename, nil }
// --------------------------------------------------------------------------- // GET /meme/[id]/[top-text]/[bottom-text] // func MemeHandler(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) var id string var topText string var botText string u, _ := url.Parse(r.RequestURI) path := u.Path[1:] if strings.LastIndex(path, ".jpg") == len(path)-4 { path = path[:len(path)-4] } parts := strings.Split(path, "/") if len(parts) > 1 { id = parts[1] if len(parts) > 2 { topText = parts[2] if len(parts) > 3 { botText = parts[3] } } } topText = strings.Replace(topText, "_", " ", -1) botText = strings.Replace(botText, "_", " ", -1) filename := cacheFilename(id, topText, botText) _, err := file.Stat(ctx, gcsFilesApiPath(bucket, filename)) if err != nil { fileWriter, _, err := file.Create(ctx, filename, &file.CreateOptions{ MIMEType: "image/jpeg", BucketName: bucket, }) defer fileWriter.Close() err = renderMeme(ctx, fileWriter, id, topText, botText) if err != nil { w.WriteHeader(http.StatusNotFound) w.Write([]byte(err.Error())) return } } location := gcsDirectPublicUrl(ctx, bucket, filename) w.Header().Set("Content-Type", "image/jpeg") w.Header().Set("Location", location) w.WriteHeader(http.StatusTemporaryRedirect) }
// --------------------------------------------------------------------------- // POST /upload // // TODO: disallow overwriting existing templates? // func UploadHandler(w http.ResponseWriter, r *http.Request) { ctx := appengine.NewContext(r) if r.Method != "POST" { w.WriteHeader(http.StatusBadRequest) return } err := r.ParseMultipartForm(10 * 1024 * 1024) if err != nil { ctx.Errorf(err.Error()) return } // TODO: validate. id := r.MultipartForm.Value["key"][0] fileHeader := r.MultipartForm.File["file"][0] contentType := fileHeader.Header["Content-Type"][0] mfile, err := fileHeader.Open() if err != nil { ctx.Errorf("Error opening uploaded file: %s", err.Error()) w.WriteHeader(http.StatusBadRequest) return } var img image.Image switch contentType { case "image/png": img, err = png.Decode(mfile) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Unable to decode PNG")) return } case "image/jpeg": img, err = jpeg.Decode(mfile) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Unable to decode JPEG")) return } default: w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("Unknown content-type '%s'", contentType))) return } // Resize such that no edge is larger than maxSize. size := img.Bounds().Size() if size.X > size.Y { if size.X > maxSize { size.Y *= maxSize / size.X size.X = maxSize } } else { if size.Y > maxSize { size.X *= maxSize / size.Y size.Y = maxSize } } img = resize.Resize(uint(size.X), uint(size.Y), img, resize.NearestNeighbor) // Create the GCS file and JPEG encode into it. filename := templateFile(id) fileWriter, _, err := file.Create(ctx, filename, &file.CreateOptions{ MIMEType: "image/jpeg", BucketName: bucket, }) if err != nil { w.WriteHeader(http.StatusInternalServerError) ctx.Errorf("Error creating %s: %s", filename, err) return } err = jpeg.Encode(fileWriter, img, &jpeg.Options{Quality: 75}) if err != nil { w.WriteHeader(http.StatusInternalServerError) fileWriter.Close() return } fileWriter.Close() // Datastore entry. key := datastore.NewKey(ctx, TemplateKind, id, 0, nil) _, err = datastore.Put(ctx, key, &Template{Id: id, Votes: 0}) if err != nil { ctx.Errorf("Error writing template entity: %s", err) w.WriteHeader(http.StatusInternalServerError) return } // Respond by showing the uploaded file. respondWithTemplate(ctx, w, id) }