一尘不染

使用GoLang mgo将PDF保存在MongoDb中

go

我读过多个有关使用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');
         });

阅读 271

收藏
2020-07-02

共1个答案

一尘不染

file通过返回Request.FormFile()类型为multipart.File是:

type File interface {
    io.Reader
    io.ReaderAt
    io.Seeker
    io.Closer
}

它实现了io.Reader,因此您可以简单地读取其内容,例如ioutil.ReadAll()

data, err := io.ReadAll(file)
// Handle error

然后:

dbSchoolPojo.Pdfdata = data

但是将大文件存储为文档的一部分并不是最佳/有效的方法。相反,看看在MongoDB的GridFS的也由支持mgoDatabase.GridFS()

这是将文件存储在MongoDB
GridFS中的方法(示例取自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()

// ...
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中的文档没有这样的字段:

type dbSchool struct {
    ID  bson.ObjectId  `json:"id" bson:"_id,omitempty"`
    ...
    Pdfdata  []byte  `json:"pdf"`
    ...
}

此类型定义将导致有一个pdfdata字段,但没有pdf。添加适当的mgostruct标记:

type dbSchool struct {
    ID  bson.ObjectId  `json:"id" bson:"_id,omitempty"`
    ...
    Pdfdata  []byte  `json:"pdf" bson:"pdf"`
    ...
}

或将所选字段从更改pdfpdfdata

2020-07-02