package trantor import ( log "github.com/cihub/seelog" "bytes" "crypto/rand" "encoding/base64" "io/ioutil" "mime/multipart" "github.com/gorilla/mux" "github.com/meskio/epubgo" "gitlab.com/trantor/trantor/lib/database" "gitlab.com/trantor/trantor/lib/parser" "gitlab.com/trantor/trantor/lib/storage" ) const ( uploadChanSize = 100 ) func InitUpload(database database.DB, store storage.Store) { uploadChannel = make(chan uploadRequest, uploadChanSize) go uploadWorker(database, store) } var uploadChannel chan uploadRequest type uploadRequest struct { file multipart.File filename string id int } func uploadWorker(database database.DB, store storage.Store) { for req := range uploadChannel { processFile(req, database, store) } } func processFile(req uploadRequest, db database.DB, store storage.Store) { defer req.file.Close() epub, err := openMultipartEpub(req.file) if err != nil { log.Warn("Not valid epub uploaded file ", req.filename, ": ", err) db.UpdateSubmission(req.id, "It is not a valid epub file", nil) return } defer epub.Close() book := parser.EpubMetadata(epub) book.ID = genID() req.file.Seek(0, 0) size, err := store.Store(book.ID, req.file, epubFile) if err != nil { log.Error("Error storing book (", book.ID, "): ", err) db.UpdateSubmission(req.id, "There was a problem in our server", nil) return } book.FileSize = int(size) book.Cover = GetCover(epub, book.ID, store) err = db.AddBook(book) if err != nil { log.Error("Error storing metadata (", book.ID, "): ", err) db.UpdateSubmission(req.id, "There was a problem in our server", nil) return } log.Info("File uploaded: ", req.filename) db.UpdateSubmission(req.id, "Waiting for moderation", &book) } func uploadPostHandler(h handler) { if h.ro { h.sess.Notify("Upload failed!", "The library is in Read Only mode, no books can be uploaded", "error") uploadHandler(h) return } h.r.ParseMultipartForm(20000000) filesForm := h.r.MultipartForm.File["epub"] submissionID := genID() for _, f := range filesForm { submission := database.Submission{ SubmissionID: submissionID, Filename: f.Filename, Status: "Waiting to be processed", } file, err := f.Open() if err != nil { log.Error("Can not open uploaded file ", f.Filename, ": ", err) h.sess.Notify("Upload problem!", "There was a problem with book "+f.Filename, "error") submission.Status = "It was not possible to read the book" h.db.AddSubmission(submission) continue } id, err := h.db.AddSubmission(submission) if err != nil { log.Error("Can add submission to db for ", f.Filename, ": ", err) } uploadChannel <- uploadRequest{file, f.Filename, id} } _uploadHandler(h, submissionID) } func uploadHandler(h handler) { _uploadHandler(h, "") } func _uploadHandler(h handler, submissionID string) { var data uploadData data.SubmissionID = submissionID data.S = GetStatus(h) data.S.Title = "Upload -- " + data.S.Title data.S.Upload = true h.load("upload", data) } type uploadData struct { S Status SubmissionID string } func submissionHandler(h handler) { var data submissionData var err error submissionID := mux.Vars(h.r)["id"] data.Submissions, err = h.db.GetSubmission(submissionID) if err != nil { log.Error("Can get submission ", submissionID, ": ", err) } data.S = GetStatus(h) data.S.Title = "Submission -- " + data.S.Title h.load("submission", data) } type submissionData struct { S Status Submissions []database.Submission } func openMultipartEpub(file multipart.File) (*epubgo.Epub, error) { buff, _ := ioutil.ReadAll(file) reader := bytes.NewReader(buff) return epubgo.Load(reader, int64(len(buff))) } func genID() string { b := make([]byte, 12) rand.Read(b) return base64.URLEncoding.EncodeToString(b) }