// New returns a new Storage that stores blobs in the // given database. The collections created will be given names with the // given prefix. func New(db *mgo.Database, collectionPrefix string) *Storage { s := &Storage{ fs: db.GridFS(collectionPrefix), } // TODO check error s.fs.Files.EnsureIndex(mgo.Index{ Key: []string{"filename"}, Unique: true, }) return s }
func getMongoFileContent(ctx *goproxy.ProxyCtx, db mgo.Database, objId bson.ObjectId) (file *mgo.GridFile, err error) { ctx.Logf("db: %+v", db) file, err = db.GridFS("fs").OpenId(objId) if err != nil { return file, err if err == mgo.ErrNotFound { } } //defer file.Close() return file, err }
// Store file in MongoDB GridFS func saveFileToMongo(db mgo.Database, objId bson.ObjectId, contentType string, openFile io.Reader, fileName string, ctx *goproxy.ProxyCtx) { ctx.Logf("db: %+v", db) mdbfile, err := db.GridFS("fs").Create(fileName) if err == nil { mdbfile.SetContentType(contentType) mdbfile.SetId(objId) ctx.Logf("Copying to: %s", fileName) _, err = io.Copy(mdbfile, openFile) if err != nil { ctx.Logf("Unable to copy to mongo: %s - %v", fileName, err) } ctx.Logf("Done copying, closing") err = mdbfile.Close() if err != nil { ctx.Logf("Unable to close copy to mongo") } ctx.Logf("MongoDB body file saved") } }
func get(w http.ResponseWriter, req *http.Request, vars martini.Params, db *mgo.Database) { // validate _id if !bson.IsObjectIdHex(vars["_id"]) { w.WriteHeader(http.StatusBadRequest) return } // define main variables _id := bson.ObjectIdHex(vars["_id"]) query := db.C(vars["coll"] + ".files").FindId(_id) meta := bson.M{} err := query.One(&meta) // found file or not if err != nil { if err.Error() == "not found" { w.WriteHeader(http.StatusNotFound) } else { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) } return } uploadDate := meta["uploadDate"].(time.Time) contentType := meta["contentType"].(string) fileName := meta["filename"].(string) req.ParseForm() head := w.Header() head.Add("Accept-Ranges", "bytes") head.Add("ETag", vars["_id"]+"+"+req.URL.RawQuery) head.Add("Date", uploadDate.Format(FORMAT)) head.Add("Last-Modified", uploadDate.Format(FORMAT)) // Expires after ten years :) head.Add("Expires", uploadDate.Add(87600*time.Hour).Format(FORMAT)) head.Add("Cache-Control", "public, max-age=31536000") head.Add("Content-Type", contentType) if _, dl := req.Form["dl"]; (contentType == "application/octet-stream") || dl { head.Add("Content-Disposition", "attachment; filename='"+fileName+"'") } // already served if h := req.Header.Get("If-None-Match"); h == vars["_id"]+"+"+req.URL.RawQuery { w.WriteHeader(http.StatusNotModified) w.Write([]byte("304 Not Modified")) return } // get file file, err := db.GridFS(vars["coll"]).OpenId(_id) defer file.Close() if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } // check to crop/resize cr, isCrop := req.Form["crop"] scr, isSCrop := req.Form["scrop"] rsz, isResize := req.Form["resize"] isIn := ^in([]string{"image/png", "image/jpeg"}, file.ContentType()) != 0 if isCrop && isIn && cr != nil { parsed, _ := parseParams(cr[0]) if parsed != nil { crop(w, file, parsed) return } } else if isSCrop && isIn && scr != nil { parsed, _ := parseParams(scr[0]) if parsed != nil { smartCrop(w, file, parsed) return } } else if isResize && isIn && rsz != nil { parsed, _ := parseParams(rsz[0]) if parsed != nil { resize(w, file, parsed) return } } else { io.Copy(w, file) } }
func post(w http.ResponseWriter, req *http.Request, vars martini.Params, db *mgo.Database) { formFile, formHead, err := req.FormFile("field") if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("400 Bad Request")) return } defer formFile.Close() //remove any directory names in the filename //START: work around IE sending full filepath and manually get filename itemHead := formHead.Header["Content-Disposition"][0] lookfor := "filename=\"" fileIndex := strings.Index(itemHead, lookfor) if fileIndex < 0 { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("400 Bad Request")) return } filename := itemHead[fileIndex+len(lookfor):] filename = filename[:strings.Index(filename, "\"")] slashIndex := strings.LastIndex(filename, "\\") if slashIndex > 0 { filename = filename[slashIndex+1:] } slashIndex = strings.LastIndex(filename, "/") if slashIndex > 0 { filename = filename[slashIndex+1:] } //END: work around IE sending full filepath // GridFs actions file, err := db.GridFS(vars["coll"]).Create(filename) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("400 Bad Request")) return } defer file.Close() io.Copy(file, formFile) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte("400 Bad Request")) return } b := make([]byte, 512) formFile.Seek(0, 0) formFile.Read(b) file.SetContentType(http.DetectContentType(b)) file.SetMeta(req.Form) err = file.Close() _id, _ := file.Id().(bson.ObjectId) // json response field := "/" + _id.Hex() + "/" + filename if !conf.TailOnly { field = "/" + vars["coll"] + field } bytes, _ := json.Marshal(map[string]interface{}{ "error": err, "field": field, }) w.Write(bytes) }