Beispiel #1
0
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
}
Beispiel #2
0
// アップロードされた画像を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
}
Beispiel #3
0
// ---------------------------------------------------------------------------
// 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)
}
Beispiel #4
0
// ---------------------------------------------------------------------------
// 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)
}