125 lines
2.7 KiB
Go
125 lines
2.7 KiB
Go
package trantor
|
|
|
|
import (
|
|
log "github.com/cihub/seelog"
|
|
|
|
"bytes"
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"io/ioutil"
|
|
"mime/multipart"
|
|
|
|
"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
|
|
}
|
|
|
|
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)
|
|
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)
|
|
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)
|
|
return
|
|
}
|
|
log.Info("File uploaded: ", req.filename)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
problem := false
|
|
|
|
h.r.ParseMultipartForm(20000000)
|
|
filesForm := h.r.MultipartForm.File["epub"]
|
|
for _, f := range filesForm {
|
|
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")
|
|
problem = true
|
|
continue
|
|
}
|
|
uploadChannel <- uploadRequest{file, f.Filename}
|
|
}
|
|
|
|
if !problem {
|
|
if len(filesForm) > 0 {
|
|
h.sess.Notify("Upload successful!", "Thank you for your contribution", "success")
|
|
} else {
|
|
h.sess.Notify("Upload problem!", "No books where uploaded.", "error")
|
|
}
|
|
}
|
|
uploadHandler(h)
|
|
}
|
|
|
|
func uploadHandler(h handler) {
|
|
var data uploadData
|
|
data.S = GetStatus(h)
|
|
data.S.Title = "Upload -- " + data.S.Title
|
|
data.S.Upload = true
|
|
h.template.load(h, "upload", data)
|
|
}
|
|
|
|
type uploadData struct {
|
|
S Status
|
|
}
|
|
|
|
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)
|
|
}
|