func (photo *Photo) Upload(r *http.Request) (err error) { c := appengine.NewContext(r) blob, err := blobstore.Create(c, r.Header.Get("X-File-Type")) if err != nil { return } defer r.Body.Close() //body, err := ioutil.ReadAll(r.Body) var buf bytes.Buffer io.Copy(&buf, r.Body) _, err = blob.Write(buf.Bytes()) if err != nil { return } _ = blob.Close() key, err := blob.Key() if err != nil { return } photo.Blob = string(key) err = photo.CreateThumb(r, buf) if err != nil { log.Println(err) err = blobstore.Delete(c, key) err = errors.New("Failed to upload image") } return }
func PutInBlobstore(c appengine.Context, toStore interface{}) (appengine.BlobKey, error) { //TODO: check capabilities var k appengine.BlobKey var data bytes.Buffer enc := gob.NewEncoder(&data) err := enc.Encode(toStore) if err != nil { c.Errorf("Datastore - PutInBlobstore - error 1 - %s", err) return k, err } w, err := blobstore.Create(c, "application/octet-stream") if err != nil { c.Errorf("Datastore - PutInBlobstore - error 2 - %s", err) return k, err } _, err = w.Write(data.Bytes()) if err != nil { c.Errorf("Datastore - PutInBlobstore - error 3 - %s", err) return k, err } err = w.Close() if err != nil { c.Errorf("Datastore - PutInBlobstore - error 4 - %s", err) return k, err } k, err = w.Key() if err != nil { c.Errorf("Datastore - PutInBlobstore - error 5 - %s", err) } return k, err }
func saveBlob(context appengine.Context, mimeType string, saveFunc func(*blobstore.Writer) error) (appengine.BlobKey, error) { var blobWriter *blobstore.Writer if w, err := blobstore.Create(context, mimeType); err == nil { blobWriter = w } else { return "", err } if err := saveFunc(blobWriter); err != nil { return "", err } if err := blobWriter.Close(); err != nil { return "", err } if k, err := blobWriter.Key(); err == nil { return k, nil } else { return "", err } return "", nil }
func (c Creature) Import(context appengine.Context) { if c.Exists(context) { return } // Fetch the source contents client := urlfetch.Client(context) resp, err := client.Get(c.Source) if err != nil { panic(err) } defer resp.Body.Close() data, err := ioutil.ReadAll(resp.Body) if err != nil { panic(err) } // Store the Blob writer, _ := blobstore.Create(context, "image/jpeg") writer.Write(data) writer.Close() c.BlobKey, _ = writer.Key() c.Save(context) }
func handleUpload(r *http.Request, p *multipart.Part) (fi *FileInfo) { fi = &FileInfo{ Name: p.FileName(), Type: p.Header.Get("Content-Type"), } if !fi.ValidateType() { return } defer func() { if rec := recover(); rec != nil { log.Println(rec) fi.Error = rec.(error).Error() } }() lr := &io.LimitedReader{R: p, N: MAX_FILE_SIZE + 1} context := appengine.NewContext(r) w, err := blobstore.Create(context, fi.Type) defer func() { w.Close() fi.Size = MAX_FILE_SIZE + 1 - lr.N fi.Key, err = w.Key() check(err) if !fi.ValidateSize() { err := blobstore.Delete(context, fi.Key) check(err) return } delayedDelete(context, fi) fi.CreateUrls(r, context) }() check(err) _, err = io.Copy(w, lr) return }
func uploadBlob(w http.ResponseWriter, r *http.Request) { bodyData, error := ioutil.ReadAll(r.Body) fileType := r.URL.Query()["type"][0] var mimeType string if fileType == "png" { mimeType = "image/png" } else { mimeType = "application/pdf" } context := appengine.NewContext(r) writer, error := blobstore.Create(context, mimeType) if error != nil { return } _, error = writer.Write(bodyData) if error != nil { return } error = writer.Close() if error != nil { return } var k appengine.BlobKey k, _ = writer.Key() encoder := json.NewEncoder(w) encoder.Encode(&UploadBlobResponse{Key: string(k)}) }
func loadImage(c appengine.Context, f *Feed) string { s := f.Link if s == "" { s = f.Url } u, err := url.Parse(s) if err != nil { return "" } u.Path = "/favicon.ico" u.RawQuery = "" u.Fragment = "" g := goon.FromContext(c) i := &Image{Id: u.String()} if err := g.Get(i); err == nil { return i.Url } client := urlfetch.Client(c) r, err := client.Get(u.String()) if err != nil || r.StatusCode != http.StatusOK || r.ContentLength == 0 { return "" } b, err := ioutil.ReadAll(r.Body) r.Body.Close() if err != nil { return "" } buf := bytes.NewBuffer(b) _, t, err := image.DecodeConfig(buf) if err != nil { t = "application/octet-stream" } else { t = "image/" + t } w, err := blobstore.Create(c, t) if err != nil { return "" } if _, err := w.Write(b); err != nil { return "" } if w.Close() != nil { return "" } i.Blob, _ = w.Key() su, err := aimage.ServingURL(c, i.Blob, &aimage.ServingURLOptions{Size: 16}) if err != nil { if err = blobstore.Delete(c, i.Blob); err != nil { c.Errorf("blob delete err: %v", err) } return "" } i.Url = su.String() g.Put(i) return i.Url }
func UpdateServingLogoUrl(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) const batch = 50 page, _ := strconv.Atoi(r.FormValue("pg")) if page < 1 { page = 1 } offset := batch * (page - 1) q := datastore.NewQuery("EmpLogo").Offset(offset).Order("IdEmp").Limit(batch) n, _ := q.Count(c) for i := q.Run(c); ; { var e model.Image key, err := i.Next(&e) if err == datastore.Done { break } // Se crea la URL para servir la oferta desde el CDN, si no se puede // se deja en blanco var imgprops image.ServingURLOptions imgprops.Secure = true imgprops.Size = 180 imgprops.Crop = false if e.Sp4 == "" && e.IdEmp != "" { var blobkey appengine.BlobKey blob, err := blobstore.Create(c, "image/jpeg") if err != nil { c.Errorf("blobstore Create: %v", e.IdEmp) } _, err = blob.Write(e.Data) if err != nil { c.Errorf("blobstore Write: %v", e.IdEmp) } err = blob.Close() if err != nil { c.Errorf("blobstore Close: %v", e.IdEmp) } blobkey, err = blob.Key() if err != nil { c.Errorf("blobstore Key Gen: %v", e.IdEmp) } if url, err := image.ServingURL(c, blobkey, &imgprops); err != nil { c.Errorf("Cannot construct EmpLogo ServingURL : %v", e.IdEmp) } else { e.Sp3 = string(blobkey) e.Sp4 = url.String() } _, err = datastore.Put(c, key, &e) if err != nil { c.Errorf("PutEmpLogo(); Error al intentar actualizar Emplogo : %v", e.IdEmp) } } } c.Infof("UpdateServingLogoUrl() Pagina: %d, actualizados: %d, del %d al %d", page, n, offset, offset+n) return }
func saveFile(c appengine.Context, b []byte) (appengine.BlobKey, error) { w, err := blobstore.Create(c, "application/json") if err != nil { return "", err } if _, err := w.Write(b); err != nil { return "", err } if err := w.Close(); err != nil { return "", err } return w.Key() }
// createBlob stores a blob in the blobstore. func createBlob(c appengine.Context, r io.Reader, contentType string) (appengine.BlobKey, error) { w, err := blobstore.Create(c, contentType) if err != nil { return "", err } if _, err := io.Copy(w, r); err != nil { return "", err } if err := w.Close(); err != nil { return "", err } return w.Key() }
func (sto *appengineStorage) ReceiveBlob(br *blobref.BlobRef, in io.Reader) (sb blobref.SizedBlobRef, err os.Error) { if sto.ctx == nil { err = errNoContext return } var b bytes.Buffer hash := br.Hash() written, err := io.Copy(io.MultiWriter(hash, &b), in) if err != nil { return } if !br.HashMatches(hash) { err = blobserver.ErrCorruptBlob return } mimeType := "application/octet-stream" bw, err := blobstore.Create(sto.ctx, mimeType) if err != nil { return } written, err = io.Copy(bw, &b) if err != nil { // TODO(bradfitz): try to clean up; close it, see if we can find the key, delete it. return } err = bw.Close() if err != nil { // TODO(bradfitz): try to clean up; see if we can find the key, delete it. return } bkey, err := bw.Key() if err != nil { return } var ent blobEnt ent.BlobRefStr = br.String() ent.Size = written ent.BlobKey = bkey dkey := datastore.NewKey(sto.ctx, blobKind, br.String(), 0, nil) _, err = datastore.Put(sto.ctx, dkey, &ent) if err != nil { blobstore.Delete(sto.ctx, bkey) // TODO: insert into task queue on error to try later? return } return blobref.SizedBlobRef{br, written}, nil }
func newBlob(c appengine.Context, p []byte) (appengine.BlobKey, error) { var k appengine.BlobKey w, err := blobstore.Create(c, "text/plain") if err != nil { return k, err } _, err = w.Write(p) if err != nil { return k, err } err = w.Close() if err != nil { return k, err } return w.Key() }
func fetch(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) imageUrl := r.FormValue("image") c.Infof("THIS IS IMAGE URL %v", imageUrl) client := urlfetch.Client(c) resp, err := client.Get(imageUrl) if error3(err, c, w) { return } blob, err := blobstore.Create(c, resp.Header.Get("Content-Type")) if error3(err, c, w) { return } written, err := io.Copy(blob, resp.Body) if error3(err, c, w) { return } if written < 100 { c.Infof("image is too small %v", written) return } err = blob.Close() if error3(err, c, w) { return } blobkey, err := blob.Key() if error3(err, c, w) { return } thumbnailUrl, err := image.ServingURL(c, blobkey, &image.ServingURLOptions{Size: 100}) if error3(err, c, w) { return } t := thumbnailUrl.String() errr := channel.Send(c, "qwerty", t) if error3(errr, c, w) { return } // c.Infof("THIS IS IMAGE URL %v", t) }
func (m *Message) images2urls(c appengine.Context) { urlc := make(chan string) for _, im := range m.images { go func(img *img_attachment) { w, err := blobstore.Create(c, img.Type) if err != nil { urlc <- err.Error() return } _, err = w.Write(img.Data) if err != nil { urlc <- err.Error() return } err = w.Close() if err != nil { urlc <- err.Error() return } key, err := w.Key() if err != nil { urlc <- err.Error() return } url, err := image.ServingURL(c, key, &image.ServingURLOptions{Secure: false, Size: 0, Crop: false}) if err != nil { urlc <- err.Error() return } urlc <- url.String() }(&im) } imagescnt := len(m.images) m.ImageUrls = make([]string, 0, imagescnt) for i := 0; i < imagescnt; i++ { u := <-urlc if strings.HasPrefix(u, "http") { m.ImageUrls = append(m.ImageUrls, u) } else { c.Errorf("Error converting image to url: %v", u) } } return }
func handleUpload(r *http.Request, p *multipart.Part) (fi *FileInfo) { fi = &FileInfo{ Name: p.FileName(), Type: p.Header.Get("Content-Type"), } if !fi.ValidateType() { return } defer func() { if rec := recover(); rec != nil { log.Println(rec) fi.Error = rec.(os.Error).String() } }() var b bytes.Buffer lr := &io.LimitedReader{p, MAX_FILE_SIZE + 1} context := appengine.NewContext(r) w, err := blobstore.Create(context, fi.Type) defer func() { w.Close() fi.Size = MAX_FILE_SIZE + 1 - lr.N fi.Key, err = w.Key() check(err) if !fi.ValidateSize() { err := blobstore.Delete(context, fi.Key) check(err) return } delayedDelete(context, fi) if b.Len() > 0 { fi.CreateThumbnail(&b, context) } fi.CreateUrls(r, context) }() check(err) var wr io.Writer = w if imageTypes.MatchString(fi.Type) { wr = io.MultiWriter(&b, w) } _, err = io.Copy(wr, lr) return }
// Given an io.Reader that will supply either a png or jpg, this crops the // image down to 100x100, encodes it as a jpg, and stores it in the blobstore. func processImage(c appengine.Context, in io.Reader) (appengine.BlobKey, error) { var bkey appengine.BlobKey m, _, err := image.Decode(in) if err != nil { return bkey, err } final := image.NewRGBA(image.Rect(0, 0, 100, 100)) draw.Draw(final, image.Rect(0, 0, 100, 100), m, image.Point{}, draw.Src) w, err := blobstore.Create(c, "application/octet-stream") if err != nil { return bkey, err } err = jpeg.Encode(w, final, nil) if err != nil { return bkey, err } err = w.Close() if err != nil { return bkey, err } return w.Key() }
func (sto *appengineStorage) ReceiveBlob(br blob.Ref, in io.Reader) (sb blob.SizedRef, err error) { loan := ctxPool.Get() defer loan.Return() ctx := loan var b bytes.Buffer written, err := io.Copy(&b, in) if err != nil { return } // bkey is non-empty once we've uploaded the blob. var bkey appengine.BlobKey // uploadBlob uploads the blob, unless it's already been done. uploadBlob := func(ctx appengine.Context) error { if len(bkey) > 0 { return nil // already done in previous transaction attempt } bw, err := blobstore.Create(ctx, "application/octet-stream") if err != nil { return err } _, err = io.Copy(bw, &b) if err != nil { // TODO(bradfitz): try to clean up; close it, see if we can find the key, delete it. ctx.Errorf("blobstore Copy error: %v", err) return err } err = bw.Close() if err != nil { // TODO(bradfitz): try to clean up; see if we can find the key, delete it. ctx.Errorf("blobstore Close error: %v", err) return err } k, err := bw.Key() if err == nil { bkey = k } return err } tryFunc := func(tc appengine.Context) error { row, err := fetchEnt(tc, br) switch err { case datastore.ErrNoSuchEntity: if err := uploadBlob(tc); err != nil { tc.Errorf("uploadBlob failed: %v", err) return err } row = &blobEnt{ Size: written, BlobKey: bkey, Namespaces: sto.namespace, } _, err = datastore.Put(tc, entKey(tc, br), row) if err != nil { return err } case nil: if row.inNamespace(sto.namespace) { // Nothing to do return nil } row.Namespaces = row.Namespaces + "|" + sto.namespace _, err = datastore.Put(tc, entKey(tc, br), row) if err != nil { return err } default: return err } // Add membership row _, err = datastore.Put(tc, sto.memKey(tc, br), &memEnt{ Size: written, }) return err } err = datastore.RunInTransaction(ctx, tryFunc, crossGroupTransaction) if err != nil { if len(bkey) > 0 { // If we just created this blob but we // ultimately failed, try our best to delete // it so it's not orphaned. blobstore.Delete(ctx, bkey) } return } return blob.SizedRef{br, uint32(written)}, nil }
func loadImage(c appengine.Context, f *Feed) { if f.ImageDate.After(time.Now()) { return } f.ImageDate = time.Now().Add(time.Hour * 24 * 7) s := f.Link if s == "" { s = f.Url } u, err := url.Parse(s) if err != nil { return } u.RawQuery = "" u.Fragment = "" p := "/favicon.ico" client := urlfetch.Client(c) if r, err := client.Get(u.String()); err == nil { b, err := ioutil.ReadAll(r.Body) r.Body.Close() if err == nil { i, err := FindIcon(b) if err == nil { p = i } } } u, err = u.Parse(p) if err != nil { return } r, err := client.Get(u.String()) if err != nil || r.StatusCode != http.StatusOK || r.ContentLength == 0 { return } b, err := ioutil.ReadAll(r.Body) r.Body.Close() if err != nil { return } buf := bytes.NewBuffer(b) _, t, err := image.DecodeConfig(buf) if err != nil { t = "application/octet-stream" } else { t = "image/" + t } w, err := blobstore.Create(c, t) if err != nil { return } if _, err := w.Write(b); err != nil { return } if w.Close() != nil { return } g := goon.FromContext(c) i := &Image{Id: u.String()} if err := g.Get(i); err == nil { blobstore.Delete(c, i.Blob) } i.Blob, _ = w.Key() su, err := aimage.ServingURL(c, i.Blob, &aimage.ServingURLOptions{Size: 16}) if err != nil { if err = blobstore.Delete(c, i.Blob); err != nil { c.Errorf("blob delete err: %v", err) } return } i.Url = su.String() g.Put(i) f.Image = i.Url }
func storeAttachments(c appengine.Context, rawAttachments []AttachmentJSON) ([]*datastore.Key, error) { keys := []*datastore.Key{} for _, rawAttachment := range rawAttachments { bytes, err := base64.StdEncoding.DecodeString(rawAttachment.Content) if err != nil { return nil, fmt.Errorf("failed to decode attachment '%v':", rawAttachment.Name, err) } w, err := blobstore.Create(c, rawAttachment.ContentType) if err != nil { return nil, fmt.Errorf("failed to create blobstore entry: %v", err) } _, err = w.Write(bytes) if err != nil { return nil, fmt.Errorf("failed to write to blobstore: %v", err) } err = w.Close() if err != nil { return nil, fmt.Errorf("failed to close blobstore entry: %v", err) } blobKey, err := w.Key() if err != nil { return nil, fmt.Errorf("failed to get key for blobstore entry: %v", err) } thumbnailURL, err := image.ServingURL(c, blobKey, &image.ServingURLOptions{ Secure: true, Size: 400, Crop: false, }) if err != nil { return nil, fmt.Errorf("failed to create thumbnail: %v", err) } bigImageURL, err := image.ServingURL(c, blobKey, &image.ServingURLOptions{ Secure: true, Size: 1600, Crop: false, }) if err != nil { return nil, fmt.Errorf("failed to create big image: %v", err) } e := Attachment{ Name: rawAttachment.Name, Content: blobKey, ContentType: rawAttachment.ContentType, CreationTime: time.Now(), Thumbnail: thumbnailURL.String(), BigImage: bigImageURL.String(), } key, err := datastore.Put(c, datastore.NewIncompleteKey(c, "Attachment", nil), &e) if err != nil { return nil, fmt.Errorf("Failed to save to datastore: %s", err) } keys = append(keys, key) } return keys, nil }
func (sto *appengineStorage) ReceiveBlob(br *blobref.BlobRef, in io.Reader) (sb blobref.SizedBlobRef, err os.Error) { if sto.ctx == nil { err = errNoContext return } var b bytes.Buffer hash := br.Hash() written, err := io.Copy(io.MultiWriter(hash, &b), in) if err != nil { return } if !br.HashMatches(hash) { err = blobserver.ErrCorruptBlob return } // bkey is non-empty once we've uploaded the blob. var bkey appengine.BlobKey // uploadBlob uploads the blob, unless it's already been done. uploadBlob := func(ctx appengine.Context) os.Error { if len(bkey) > 0 { return nil // already done in previous transaction attempt } bw, err := blobstore.Create(ctx, "application/octet-stream") if err != nil { return err } _, err = io.Copy(bw, &b) if err != nil { // TODO(bradfitz): try to clean up; close it, see if we can find the key, delete it. ctx.Errorf("blobstore Copy error: %v", err) return err } err = bw.Close() if err != nil { // TODO(bradfitz): try to clean up; see if we can find the key, delete it. ctx.Errorf("blobstore Close error: %v", err) return err } k, err := bw.Key() if err == nil { bkey = k } return err } tryFunc := func(tc appengine.Context) os.Error { row, err := fetchEnt(sto.ctx, br) switch err { case datastore.ErrNoSuchEntity: if err := uploadBlob(sto.ctx); err != nil { tc.Errorf("uploadBlob failed: %v", err) return err } row = &blobEnt{ Size: []byte(fmt.Sprintf("%d", written)), BlobKey: []byte(string(bkey)), Namespaces: []byte(sto.namespace), } _, err = datastore.Put(tc, entKey(tc, br), row) if err != nil { return err } case nil: if row.inNamespace(sto.namespace) { // Nothing to do return nil } row.Namespaces = []byte(string(row.Namespaces) + "|" + sto.namespace) _, err = datastore.Put(tc, entKey(tc, br), row) if err != nil { return err } default: return err } // Add membership row _, err = datastore.Put(tc, sto.memKey(tc, br), &memEnt{ Size: []byte(fmt.Sprintf("%d", written)), }) return err } err = datastore.RunInTransaction(sto.ctx, tryFunc, crossGroupTransaction) if err != nil { if len(bkey) > 0 { // If we just created this blob but we // ultimately failed, try our best to delete // it so it's not orphaned. blobstore.Delete(sto.ctx, bkey) } return } return blobref.SizedBlobRef{br, written}, nil }
func (photo *Photo) CreateThumb(r *http.Request, buf bytes.Buffer) (err error) { c := appengine.NewContext(r) var img image.Image //img, err := png.Decode(&buf) if r.Header.Get("X-File-Type") == "image/png" { img, err = png.Decode(&buf) } else if r.Header.Get("X-File-Type") == "image/jpg" || r.Header.Get("X-File-Type") == "image/jpeg" { img, err = jpeg.Decode(&buf) } else { img, _, err = image.Decode(&buf) } if err != nil { return } // Resize if too large, for more efficient resizing // We aim forl ess than 1200 pixels in any dimension; if the // picture is larger than that, we squeeze it down to 300 const max = 1200 if b := img.Bounds(); b.Dx() > max || b.Dy() > max { // If it's gigantic, it's more efficient to downsample first // and then resize; resizing will smooth out the roughness if b.Dx() > 2*max || b.Dy() > 2*max { w, h := max, max if b.Dx() > b.Dy() { h = b.Dy() * h / b.Dx() } else { w = b.Dx() * w / b.Dy() } img = resize.Resample(img, img.Bounds(), w, h) b = img.Bounds() } w, h := max/2, max/2 if b.Dx() > b.Dy() { h = b.Dy() * h / b.Dx() } else { w = b.Dx() * w / b.Dy() } img = resize.Resize(img, img.Bounds(), w, h) } buf.Reset() err = jpeg.Encode(&buf, img, nil) blob, err := blobstore.Create(c, r.Header.Get("X-File-Type")) if err != nil { return } _, err = blob.Write(buf.Bytes()) if err != nil { return } _ = blob.Close() key, err := blob.Key() if err != nil { return } photo.Thumb = string(key) return }
func save(c appengine.Context, p *painting.Painting) error { if p.Image.URL != "" { // Fetch the image. res, err := urlfetch.Client(c).Get(p.Image.URL) if err != nil { logger.Error(c, err) return err } defer res.Body.Close() // Save what we read to decode the image config, // so we can save the whole image to the blobstore. buf := &bytes.Buffer{} t := io.TeeReader(res.Body, buf) // Decode the config to get the size and content type. conf, ext, err := image.DecodeConfig(t) if err != nil { logger.Error(c, err) return err } p.Image.Width = conf.Width p.Image.Height = conf.Height // Create a new blob. b, err := blobstore.Create(c, "image/"+ext) if err != nil { logger.Error(c, err) return err } // Copy the image into it. // Prepend what we read to decode the image config. r := io.MultiReader(buf, res.Body) _, err = io.Copy(b, r) if err != nil { logger.Error(c, err) return err } err = b.Close() if err != nil { logger.Error(c, err) return err } // Add the image to the painting. p.Image.BlobKey, err = b.Key() if err != nil { logger.Error(c, err) return err } u, err := aeimage.ServingURL(c, p.Image.BlobKey, nil) if err != nil { logger.Error(c, err) return err } p.Image.URL = u.String() } return p.Save(c) }
/* * 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 }
func nutCreateHandler(c appengine.Context, w http.ResponseWriter, r *http.Request) { d := make(ContentData) ct := r.Header.Get("Content-Type") putNut := ct == "application/zip" if !putNut { err := fmt.Errorf(`Unexpected Content-Type %q, should be "application/zip".`, ct) ServeJSONError(w, http.StatusNotAcceptable, err, d) return } vendor := r.URL.Query().Get(":vendor") name := r.URL.Query().Get(":name") ver := r.URL.Query().Get(":version") if vendor == "" || !nutp.VendorRegexp.MatchString(vendor) || name == "" || (ver != "" && !nutp.VersionRegexp.MatchString(ver)) { err := fmt.Errorf("Invalid vendor %q, name %q or version %q.", vendor, name, ver) ServeJSONError(w, http.StatusBadRequest, err, d) return } // extract token from request token := r.URL.Query().Get("token") if token == "" { ServeJSONError(w, http.StatusForbidden, fmt.Errorf("Can't find 'token' in get parameters."), d) return } // find user by token q := datastore.NewQuery("User").KeysOnly().Filter("Token=", token) userKeys, err := q.Limit(2).GetAll(c, nil) if err != nil || len(userKeys) != 1 { if err == nil || err == datastore.ErrNoSuchEntity { err = fmt.Errorf("Can't find user with token %q.", token) } ServeJSONError(w, http.StatusForbidden, err, d) return } userID := userKeys[0].StringID() // user should belong to vendor v := gonuts.Vendor{} err = datastore.Get(c, gonuts.VendorKey(c, vendor), &v) if err == datastore.ErrNoSuchEntity { err = fmt.Errorf("Can't find vendor %q.", vendor) ServeJSONError(w, http.StatusNotFound, err, d) return } if err != nil { ServeJSONError(w, http.StatusInternalServerError, err, d) return } found := false for _, id := range v.UserStringID { if id == userID { found = true break } } if !found { err = fmt.Errorf("You don't have publish access to vendor %q.", vendor) ServeJSONError(w, http.StatusForbidden, err, d) return } // nut version should not exist nutKey := gonuts.NutKey(c, vendor, name) nut := gonuts.Nut{Vendor: vendor, Name: name} versionKey := gonuts.VersionKey(c, vendor, name, ver) version := gonuts.Version{Vendor: vendor, Name: name, Version: ver, CreatedAt: time.Now()} err = datastore.Get(c, versionKey, &version) if err != nil && err != datastore.ErrNoSuchEntity { ServeJSONError(w, http.StatusInternalServerError, err, d) return } if err == nil { ServeJSONError(w, http.StatusConflict, fmt.Errorf("Nut %s/%s version %s already exists.", vendor, name, ver), d) return } // read nut from request body nf := new(nutp.NutFile) b, err := ioutil.ReadAll(r.Body) if err == nil { _, err = nf.ReadFrom(bytes.NewReader(b)) } if err != nil { ServeJSONError(w, http.StatusBadRequest, err, d) return } nut.Doc = nf.Doc version.Doc = nf.Doc version.Homepage = nf.Homepage version.VersionNum = nf.Version.Major*1000000 + nf.Version.Minor*1000 + nf.Version.Patch // for sorting // check vendor, name and version match if nf.Vendor != vendor || nf.Name != name || nf.Version.String() != ver { err = fmt.Errorf("Nut vendor %q, name %q and version %q from URL don't match found in body: %q %q %q.", vendor, name, ver, nf.Vendor, nf.Name, nf.Version.String()) ServeJSONError(w, http.StatusBadRequest, err, d) return } // check nut errors := nf.Check() if len(errors) != 0 { err = fmt.Errorf("%s", strings.Join(errors, "\n")) ServeJSONError(w, http.StatusBadRequest, err, d) return } // store nut blob bw, err := blobstore.Create(c, ct) if err == nil { _, err = bw.Write(b) if err == nil { err = bw.Close() } } if err != nil { ServeJSONError(w, http.StatusInternalServerError, err, d) return } // store nut version blobKey, err := bw.Key() if err == nil { version.BlobKey = blobKey _, err = datastore.Put(c, versionKey, &version) } if err != nil { ServeJSONError(w, http.StatusInternalServerError, err, d) return } // store nut with new doc _, err = datastore.Put(c, nutKey, &nut) if err != nil { ServeJSONError(w, http.StatusInternalServerError, err, d) return } // update search index err = gonuts.AddToSearchIndex(c, &nut) gonuts.LogError(c, err) // done! d["Message"] = fmt.Sprintf("Nut %s/%s version %s published.", vendor, name, ver) ServeJSON(w, http.StatusCreated, d) return }
func (i *ImageIndex) FetchImage(info imageInfo, pageID string) { i.wg.Add(1) _, err := i.s.Conn.Storage("Image").NewQuery().KeysOnly(). Filter("Location", model.EQ, info.src).GetFirst(nil) if err != model.ErrNotFound { i.s.Log("Error: %s\n", "galleyes: indexed image") i.wg.Done() return } resp, err := i.s.Client.Get(info.src) if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } mime := resp.Header.Get("Content-Type") if mime != "image/png" && mime != "image/jpeg" && mime != "image/gif" { i.s.Log("Error: %s - %s - %s\n", "galleyes: not supported image format", mime, info.src) i.wg.Done() return } data, err := ioutil.ReadAll(resp.Body) if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } // caculate PHash var buff bytes.Buffer _, err = buff.Write(data) if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } m, _, err := tipimage.Decode(&buff) if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } hash, part := PHash(m) // caculate md5 checksum h := md5.New() _, err = h.Write(data) if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } checksum := h.Sum(nil) // save the original image w, err := blobstore.Create(i.s.Context, mime) if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } w.Write(data) _, err = w.Write(data) if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } err = w.Close() if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } key, err := w.Key() if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } link, err := imgs.ServingURL(i.s.Context, key, nil) if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } // assign value img := Image{} img.PageID = pageID img.SavedID = string(key) img.SavedLocation = link.String() img.Location = info.src img.Description = info.alt img.CheckSum = base64.URLEncoding.EncodeToString(checksum) img.PHash = hash img.Part0 = part[0] img.Part1 = part[1] img.Part2 = part[2] img.Part3 = part[3] img.Part4 = part[4] img.Part5 = part[5] img.Part6 = part[6] img.Part7 = part[7] _, err = i.s.Conn.Storage("Image").Put(&img) if err != nil { i.s.Log("Error: %s\n", err.Error()) i.wg.Done() return } i.wg.Done() }
// upload is the HTTP handler for uploading images; it handles "/". func upload(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) var imgprops appimage.ServingURLOptions imgprops.Secure = true imgprops.Size = 180 imgprops.Crop = false if s, ok := sess.IsSess(w, r, c); ok { u, _ := model.GetCta(c, s.User) emp, err := u.GetEmpresa(c, r.FormValue("IdEmp")) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } imgo := model.GetLogo(c, r.FormValue("IdEmp")) if imgo == nil { imgo = new(model.Image) imgo.IdEmp = emp.IdEmp } fd := imgToForm(*imgo) tc := make(map[string]interface{}) tc["Sess"] = s tc["Empresa"] = emp tc["FormData"] = fd if r.Method != "POST" { // No upload; show the upload form. micrositio(w, r) return } idemp := r.FormValue("IdEmp") sp1 := r.FormValue("Sp1") sp2 := r.FormValue("Sp2") f, _, err := r.FormFile("image") model.Check(err) defer f.Close() // Grab the image data var buf bytes.Buffer io.Copy(&buf, f) i, _, err := image.Decode(&buf) if err != nil { if r.FormValue("tipo") == "async" { //w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, "<p>'%s'</p>", "No se actualizó el logotipo, formato no aceptado") } else { tc["Error"] = struct{ Badformat string }{"badformat"} micrositioTpl.Execute(w, tc) } return } const max = 600 // We aim for less than max pixels in any dimension. if b := i.Bounds(); b.Dx() > max || b.Dy() > max { // If it's gigantic, it's more efficient to downsample first // and then resize; resizing will smooth out the roughness. if b.Dx() > 2*max || b.Dy() > 2*max { w, h := max*2, max*2 if b.Dx() > b.Dy() { h = b.Dy() * h / b.Dx() } else { w = b.Dx() * w / b.Dy() } i = resize.Resample(i, i.Bounds(), w, h) b = i.Bounds() } w, h := max, max if b.Dx() > b.Dy() { h = b.Dy() * h / b.Dx() } else { w = b.Dx() * w / b.Dy() } i = resize.Resize(i, i.Bounds(), w, h) } // Encode as a new JPEG image. buf.Reset() err = jpeg.Encode(&buf, i, nil) if err != nil { if r.FormValue("tipo") == "async" { fmt.Fprintf(w, "<p>'%s'</p>", "No se actualizó el logotipo, formato no aceptado") } else { tc["Error"] = struct{ Badencode string }{"badencode"} micrositioTpl.Execute(w, tc) } return } var blobkey appengine.BlobKey blob, err := blobstore.Create(c, "image/jpeg") if err != nil { c.Errorf("blobstore Create: %v", idemp) } _, err = blob.Write(buf.Bytes()) if err != nil { c.Errorf("blobstore Write: %v", idemp) } err = blob.Close() if err != nil { c.Errorf("blobstore Close: %v", idemp) } blobkey, err = blob.Key() if err != nil { c.Errorf("blobstore Key Gen: %v", idemp) } if url, err := appimage.ServingURL(c, blobkey, &imgprops); err != nil { c.Errorf("Cannot construct EmpLogo ServingURL : %v", idemp) } else { // Save the image under a unique key, a hash of the image. img := &model.Image{ Data: buf.Bytes(), IdEmp: idemp, IdImg: model.RandId(20), Kind: "EmpLogo", Name: imgo.Name, Desc: imgo.Desc, Sizepx: 0, Sizepy: 0, Url: imgo.Url, Type: "", Sp1: sp1, Sp2: sp2, Sp3: string(blobkey), Sp4: url.String(), Np1: 0, Np2: 0, Np3: 0, Np4: 0, } _, err = model.PutLogo(c, img) if err != nil { if r.FormValue("tipo") == "async" { fmt.Fprintf(w, "<p>'%s'</p>", "No se actualizó el logotipo. Sistema en matenimiento, intente en unos minutos") } else { tc["Error"] = struct{ Cantsave string }{"cantsave"} micrositioTpl.Execute(w, tc) } return } } /* se crea icono */ val := slogores(c, idemp, 70, 0) if val != 0 { tc["Error"] = struct{ Cantsave string }{"cantsave"} micrositioTpl.Execute(w, tc) return } if r.FormValue("tipo") == "async" { fmt.Fprintf(w, "<p></p>") } else { micrositio(w, r) } return } else { http.Redirect(w, r, "/r/registro", http.StatusFound) } }
// rotate rotates the Painting's image counter-clockwise by angle in degrees. // angle modulo 360 must be one of 0, 90, 180, 270. func (p *Painting) rotate(c appengine.Context, angle int) error { switch math.Abs(float64(angle % 360)) { case 0, 90, 180, 270: break default: return errors.New(fmt.Sprintf("painting: Unsupported angle %f.", angle)) } if p.Image == (Image{}) { return nil } // Read the image from the blobstore. r := blobstore.NewReader(c, p.Image.BlobKey) src, _, err := image.Decode(r) if err != nil { return err } // Create the rotated image. srcRect := src.Bounds() var dstRect image.Rectangle if angle == 0 || angle == 180 { dstRect = srcRect } else { dstRect = image.Rect(0, 0, srcRect.Dy(), srcRect.Dx()) } dst := image.NewNRGBA(dstRect) err = graphics.Rotate(dst, src, &graphics.RotateOptions{ Angle: float64(angle%360) * math.Pi / 180, }) if err != nil { return err } // Create a new blob for the rotated image. w, err := blobstore.Create(c, "image/png") if err != nil { return err } err = png.Encode(w, dst) if err != nil { return err } err = w.Close() if err != nil { return err } // Delete the old blob. deleteBlobLater.Call(c, p.Image.BlobKey) // Update the image metadata. p.Image.BlobKey, err = w.Key() if err != nil { return err } p.Image.Width = dstRect.Dx() p.Image.Height = dstRect.Dy() u, err := aeimage.ServingURL(c, p.Image.BlobKey, nil) if err != nil { return err } p.Image.URL = u.String() err = p.Save(c) if err != nil { return err } return nil }