我读过多个有关使用mgo保存文件的博客,但找不到满足特定需求的解决方案,请大声喊叫!
下面在MongoDb中插入对象:
var dbSchoolPojo dbSchool i := bson.NewObjectId() dbSchoolPojo.ID = i coll := db.C("school") coll.Insert(&dbSchoolPojo)
下面能够保存文件:
file, handler, err := r.FormFile("pdf") //Able to get file from r *http.Request
现在,在插入对象之前,我需要将上述文件设置为:
dbSchoolPojo.pdf = file.Bytes(); //Of course Bytes() is invalid method
我的结构对象:
type dbSchool struct { ID bson.ObjectId `json:"id" bson:"_id,omitempty"` ... Pdf []byte `json:"pdf" bson:"pdf"` ... }
用外行术语来说,问题是:如何使用mgo驱动程序通过GoLang结构在mongoDb中插入文件(从HTML表单接收)?
谢谢阅读!:)
更新:
PDF存储在MongoDB中,如下所示:
Binary('EWHKDSH876KJHlkjdswsddsfsd3232432njnjkn2dljDSFSDFIJSFD333...')
以下代码可以正常工作,但不提供PDF文件:
func DownloadPdf(w http.ResponseWriter, r *http.Request, db mongoDB) { var school dbSchool coll := db.C("schools") incomingId = "59e6404e2f68182a74610f19"; //This mongo DB _id is received from GET URL request err := coll.Find(bson.M{"_id": bson.ObjectIdHex(incomingId)}). Select(bson.M{"pdf": 1}).One(&school) if err != nil { serve404(w, r, db) return } buffer := school.Pdf w.Header().Set("Content-Disposition", "attachment; filename=abc.pdf") w.Header().Set("Content-Type", "application/pdf") w.Header().Set("Content-Length", strconv.Itoa(len(buffer))) if _, err := w.Write(buffer); err != nil { log.Println("unable to serve image.") //This line is not executed } }
jQuery代码以请求内容:
$(".downloadPdfFile").click(function() { var domain = document.location.origin; window.open(domain+'/brochure/59e6404e2f68182a74610f19', '_blank'); });
将file通过返回Request.FormFile()类型为multipart.File是:
file
Request.FormFile()
multipart.File
type File interface { io.Reader io.ReaderAt io.Seeker io.Closer }
它实现了io.Reader,因此您可以简单地读取其内容,例如ioutil.ReadAll():
io.Reader
ioutil.ReadAll()
data, err := io.ReadAll(file) // Handle error
然后:
dbSchoolPojo.Pdfdata = data
但是将大文件存储为文档的一部分并不是最佳/有效的方法。相反,看看在MongoDB的GridFS的也由支持mgo:Database.GridFS()。
mgo
Database.GridFS()
这是将文件存储在MongoDB GridFS中的方法(示例取自GridFS.Create()):
GridFS.Create()
func check(err error) { if err != nil { panic(err.String()) } } file, err := db.GridFS("fs").Create("myfile.txt") check(err) n, err := file.Write([]byte("Hello world!")) check(err) err = file.Close() check(err) fmt.Printf("%d bytes written\n", n)
使用GridFS,您还可以保存文件,而无需先将其所有内容读取到内存中(如果将文件内容“流式传输”到mgo.GridFile实现中)io.Writer。致电io.Copy():
GridFS
mgo.GridFile
io.Writer
io.Copy()
// ... file, handler, err := r.FormFile("pdfFile") // ... mongoFile, err := db.GridFS("fs").Create("somepdf.pdf") check(err) // Now stream from HTTP request into the mongo file: written, err := io.Copy(mongoFile, file) // Handle err err = mongoFile.Close() check(err)
编辑:更新回答您的更新
提供PDF时,您以错误的方式查询文档:
err := coll.Find(bson.M{"_id": bson.ObjectIdHex(incomingId)}). Select(bson.M{"pdf": 1}).One(&school)
您选择pdf要检索的字段,但是您在MongoDB中的文档没有这样的字段:
pdf
type dbSchool struct { ID bson.ObjectId `json:"id" bson:"_id,omitempty"` ... Pdfdata []byte `json:"pdf"` ... }
此类型定义将导致有一个pdfdata字段,但没有pdf。添加适当的mgostruct标记:
pdfdata
type dbSchool struct { ID bson.ObjectId `json:"id" bson:"_id,omitempty"` ... Pdfdata []byte `json:"pdf" bson:"pdf"` ... }
或将所选字段从更改pdf为pdfdata。