func get(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { http.Redirect(w, r, WEBSITE, http.StatusFound) return } parts := strings.Split(r.URL.Path, "/") if len(parts) == 3 { if key := parts[1]; key != "" { blobKey := appengine.BlobKey(key) bi, err := blobstore.Stat(appengine.NewContext(r), blobKey) if err == nil { w.Header().Add("X-Content-Type-Options", "nosniff") if !imageTypes.MatchString(bi.ContentType) { w.Header().Add("Content-Type", "application/octet-stream") w.Header().Add( "Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", parts[2]), ) } w.Header().Add( "Cache-Control", fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME), ) blobstore.Send(w, blobKey) return } } } http.Error(w, "404 Not Found", http.StatusNotFound) }
func RestoreTask(w http.ResponseWriter, r *http.Request) { blobKey := appengine.BlobKey(r.FormValue("blobKey")) c := appengine.NewContext(r) blobInfo, err := blobstore.Stat(c, blobKey) if err != nil { c.Errorf("%v", err) return } c.Infof("Restoring from %s", blobInfo.Filename) reader := blobstore.NewReader(c, blobKey) LoadDB(c, reader) }
func handleDownload(ctx *Context, w http.ResponseWriter, r *http.Request) error { blobKey := appengine.BlobKey(r.FormValue("id")) stat, err := blobstore.Stat(ctx.c, blobKey) if err == datastore.ErrNoSuchEntity { return ctx.NotFound() } if err != nil { return err } hdr := w.Header() hdr.Set("Content-Disposition", "attachment; filename="+stat.Filename) hdr.Set("X-AppEngine-BlobKey", string(blobKey)) return nil }
func storeImage(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) if err := users.CheckPerm(w, r, users.OP_UPDATE); err != nil { return } blobs, _, err := blobstore.ParseUpload(r) if err != nil { app.ServeError(c, w, err) return } file := blobs["img"] if len(file) == 0 { app.ServeError(c, w, errors.New(ERR_FILENOTSTORED)) return } key := file[0].BlobKey info, err := blobstore.Stat(c, key) if err != nil { app.ServeError(c, w, err) return } if info.Size > MAXSZIMAGE { blobstore.Delete(c, key) app.ServeError(c, w, errors.New(ERR_FILENOTVALID)) return } /* key,err=resizeImage(c,key) if err != nil { app.ServeError(c, w, errors.New(ERR_FILENOTVALID)) return } */ fmt.Fprintf(w, "%s", string(key)) }
func serveThumbnail(w http.ResponseWriter, r *http.Request) { parts := strings.Split(r.URL.Path, "/") if len(parts) == 3 { if key := parts[2]; key != "" { var data []byte c := appengine.NewContext(r) item, err := memcache.Get(c, key) if err == nil { data = item.Value } else { blobKey := appengine.BlobKey(key) if _, err = blobstore.Stat(c, blobKey); err == nil { fi := FileInfo{Key: blobKey} data, _ = fi.CreateThumbnail( blobstore.NewReader(c, blobKey), c, ) } } if err == nil && len(data) > 3 { w.Header().Add( "Cache-Control", fmt.Sprintf("public,max-age=%d", EXPIRATION_TIME), ) contentType := "image/png" if string(data[:3]) == "GIF" { contentType = "image/gif" } else if string(data[1:4]) != "PNG" { contentType = "image/jpeg" } w.Header().Set("Content-Type", contentType) fmt.Fprintln(w, string(data)) return } } } http.Error(w, "404 Not Found", http.StatusNotFound) }
/* * Handles individual blobs. * * - Only supported image types will be processed. Others will be returned as-is. * - Resizes the image if necessary. * - Writes the new compressed JPEG to blobstore. * - Deletes the old blob and substitutes the old BlobInfo with the new one. */ func handleBlob(options *compressionOptions, blobOriginal *blobstore.BlobInfo) (blob *blobstore.BlobInfo) { blob = blobOriginal // Check that the blob is of supported mime-type if !validateMimeType(blob) { return } // Instantiate blobstore reader reader := blobstore.NewReader(options.Context, blob.BlobKey) // Instantiate the image object img, _, err := image.Decode(reader) if err != nil { return } // Resize if necessary // Maintain aspect ratio! if options.Size > 0 && (img.Bounds().Max.X > options.Size || img.Bounds().Max.Y > options.Size) { size_x := img.Bounds().Max.X size_y := img.Bounds().Max.Y if size_x > options.Size { size_x_before := size_x size_x = options.Size size_y = int(math.Floor(float64(size_y) * float64(float64(size_x)/float64(size_x_before)))) } if size_y > options.Size { size_y_before := size_y size_y = options.Size size_x = int(math.Floor(float64(size_x) * float64(float64(size_y)/float64(size_y_before)))) } img = resize.Resize(img, img.Bounds(), size_x, size_y) } // JPEG options o := &jpeg.Options{ Quality: options.Quality, } // Open writer writer, err := blobstore.Create(options.Context, "image/jpeg") if err != nil { return } // Write to blobstore if err := jpeg.Encode(writer, img, o); err != nil { _ = writer.Close() return } // Close writer if err := writer.Close(); err != nil { return } // Get key newKey, err := writer.Key() if err != nil { return } // Get new BlobInfo newBlobInfo, err := blobstore.Stat(options.Context, newKey) if err != nil { return } // All good! // Now replace the old blob and delete it deleteOldBlob(options, blob.BlobKey) blob = newBlobInfo return }