2014-06-28 23:07:34 +08:00
|
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
import (
|
2015-10-17 17:15:33 +08:00
|
|
|
|
"encoding/base64"
|
|
|
|
|
"fmt"
|
|
|
|
|
"github.com/leanote/leanote/app/db"
|
|
|
|
|
"github.com/leanote/leanote/app/info"
|
2014-09-19 17:18:53 +08:00
|
|
|
|
. "github.com/leanote/leanote/app/lea"
|
2014-06-28 23:07:34 +08:00
|
|
|
|
"github.com/revel/revel"
|
2014-09-02 15:45:44 +08:00
|
|
|
|
"gopkg.in/mgo.v2/bson"
|
2015-10-17 17:15:33 +08:00
|
|
|
|
"io/ioutil"
|
|
|
|
|
"net/http"
|
2014-06-28 23:07:34 +08:00
|
|
|
|
"os"
|
2014-09-21 22:52:37 +08:00
|
|
|
|
"strings"
|
2015-10-17 17:15:33 +08:00
|
|
|
|
"time"
|
2014-06-28 23:07:34 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const DEFAULT_ALBUM_ID = "52d3e8ac99c37b7f0d000001"
|
|
|
|
|
|
|
|
|
|
type FileService struct {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add Image
|
2015-01-08 22:08:09 +08:00
|
|
|
|
func (this *FileService) AddImage(image info.File, albumId, userId string, needCheckSize bool) (ok bool, msg string) {
|
2014-06-28 23:07:34 +08:00
|
|
|
|
image.CreatedTime = time.Now()
|
|
|
|
|
if albumId != "" {
|
|
|
|
|
image.AlbumId = bson.ObjectIdHex(albumId)
|
|
|
|
|
} else {
|
|
|
|
|
image.AlbumId = bson.ObjectIdHex(DEFAULT_ALBUM_ID)
|
|
|
|
|
image.IsDefaultAlbum = true
|
|
|
|
|
}
|
|
|
|
|
image.UserId = bson.ObjectIdHex(userId)
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2015-01-08 22:08:09 +08:00
|
|
|
|
ok = db.Insert(db.Files, image)
|
|
|
|
|
return
|
2014-06-28 23:07:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// list images
|
|
|
|
|
// if albumId == "" get default album images
|
|
|
|
|
func (this *FileService) ListImagesWithPage(userId, albumId, key string, pageNumber, pageSize int) info.Page {
|
|
|
|
|
skipNum, sortFieldR := parsePageAndSort(pageNumber, pageSize, "CreatedTime", false)
|
|
|
|
|
files := []info.File{}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
q := bson.M{"UserId": bson.ObjectIdHex(userId), "Type": ""} // life
|
2014-06-28 23:07:34 +08:00
|
|
|
|
if albumId != "" {
|
2015-11-13 17:58:41 +08:00
|
|
|
|
q["AlbumId"] = bson.ObjectIdHex(albumId)
|
2014-06-28 23:07:34 +08:00
|
|
|
|
} else {
|
|
|
|
|
q["IsDefaultAlbum"] = true
|
|
|
|
|
}
|
|
|
|
|
if key != "" {
|
2015-11-13 17:58:41 +08:00
|
|
|
|
q["Title"] = bson.M{"$regex": bson.RegEx{".*?" + key + ".*", "i"}}
|
2014-06-28 23:07:34 +08:00
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
|
|
|
|
// LogJ(q)
|
|
|
|
|
|
|
|
|
|
count := db.Count(db.Files, q)
|
|
|
|
|
|
2014-06-28 23:07:34 +08:00
|
|
|
|
db.Files.
|
|
|
|
|
Find(q).
|
|
|
|
|
Sort(sortFieldR).
|
|
|
|
|
Skip(skipNum).
|
|
|
|
|
Limit(pageSize).
|
|
|
|
|
All(&files)
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-06-28 23:07:34 +08:00
|
|
|
|
return info.Page{Count: count, List: files}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (this *FileService) UpdateImageTitle(userId, fileId, title string) bool {
|
|
|
|
|
return db.UpdateByIdAndUserIdField(db.Files, fileId, userId, "Title", title)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get all images names
|
|
|
|
|
// for upgrade
|
|
|
|
|
func (this *FileService) GetAllImageNamesMap(userId string) (m map[string]bool) {
|
|
|
|
|
q := bson.M{"UserId": bson.ObjectIdHex(userId)}
|
|
|
|
|
files := []info.File{}
|
|
|
|
|
db.ListByQWithFields(db.Files, q, []string{"Name"}, &files)
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-06-28 23:07:34 +08:00
|
|
|
|
m = make(map[string]bool)
|
|
|
|
|
if len(files) == 0 {
|
|
|
|
|
return
|
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-06-28 23:07:34 +08:00
|
|
|
|
for _, file := range files {
|
|
|
|
|
m[file.Name] = true
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// delete image
|
|
|
|
|
func (this *FileService) DeleteImage(userId, fileId string) (bool, string) {
|
|
|
|
|
file := info.File{}
|
|
|
|
|
db.GetByIdAndUserId(db.Files, fileId, userId, &file)
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
|
|
|
|
if file.FileId != "" {
|
2014-06-28 23:07:34 +08:00
|
|
|
|
if db.DeleteByIdAndUserId(db.Files, fileId, userId) {
|
|
|
|
|
// delete image
|
2014-09-19 17:18:53 +08:00
|
|
|
|
// TODO
|
2014-09-21 22:52:37 +08:00
|
|
|
|
file.Path = strings.TrimLeft(file.Path, "/")
|
|
|
|
|
var err error
|
|
|
|
|
if strings.HasPrefix(file.Path, "upload") {
|
|
|
|
|
Log(file.Path)
|
|
|
|
|
err = os.Remove(revel.BasePath + "/public/" + file.Path)
|
|
|
|
|
} else {
|
|
|
|
|
err = os.Remove(revel.BasePath + "/" + file.Path)
|
|
|
|
|
}
|
2014-06-28 23:07:34 +08:00
|
|
|
|
if err == nil {
|
|
|
|
|
return true, ""
|
|
|
|
|
}
|
|
|
|
|
return false, "delete file error!"
|
|
|
|
|
}
|
|
|
|
|
return false, "db error"
|
|
|
|
|
}
|
|
|
|
|
return false, "no such item"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// update image title
|
|
|
|
|
func (this *FileService) UpdateImage(userId, fileId, title string) bool {
|
|
|
|
|
return db.UpdateByIdAndUserIdField(db.Files, fileId, userId, "Title", title)
|
2014-09-19 17:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-17 17:15:33 +08:00
|
|
|
|
func (this *FileService) GetFileBase64(userId, fileId string) (str string, mine string) {
|
|
|
|
|
defer func() { // 必须要先声明defer,否则不能捕获到panic异常
|
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
|
fmt.Println(err) // 这里的err其实就是panic传入的内容,55
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
path := this.GetFile(userId, fileId)
|
|
|
|
|
|
|
|
|
|
if path == "" {
|
|
|
|
|
return "", ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
path = revel.BasePath + "/" + strings.TrimLeft(path, "/")
|
|
|
|
|
|
|
|
|
|
ff, err := ioutil.ReadFile(path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e64 := base64.StdEncoding
|
|
|
|
|
maxEncLen := e64.EncodedLen(len(ff))
|
|
|
|
|
encBuf := make([]byte, maxEncLen)
|
|
|
|
|
|
|
|
|
|
e64.Encode(encBuf, ff)
|
|
|
|
|
|
|
|
|
|
mime := http.DetectContentType(ff)
|
|
|
|
|
|
|
|
|
|
str = string(encBuf)
|
|
|
|
|
return str, mime
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 得到图片base64, 图片要在之前添加data:image/png;base64,
|
|
|
|
|
func (this *FileService) GetImageBase64(userId, fileId string) string {
|
|
|
|
|
|
|
|
|
|
str, mime := this.GetFileBase64(userId, fileId)
|
|
|
|
|
if str == "" {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
switch mime {
|
|
|
|
|
case "image/gif", "image/jpeg", "image/pjpeg", "image/png", "image/tiff":
|
|
|
|
|
return fmt.Sprintf("data:%s;base64,%s", mime, str)
|
|
|
|
|
default:
|
|
|
|
|
}
|
|
|
|
|
return "data:image/png;base64," + str
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
// 获取文件路径
|
|
|
|
|
// 要判断是否具有权限
|
|
|
|
|
// userId是否具有fileId的访问权限
|
|
|
|
|
func (this *FileService) GetFile(userId, fileId string) string {
|
2014-09-20 15:20:36 +08:00
|
|
|
|
if fileId == "" {
|
2014-09-19 17:18:53 +08:00
|
|
|
|
return ""
|
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
file := info.File{}
|
|
|
|
|
db.Get(db.Files, fileId, &file)
|
|
|
|
|
path := file.Path
|
|
|
|
|
if path == "" {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
// 1. 判断权限
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
// 是否是我的文件
|
2014-09-20 15:20:36 +08:00
|
|
|
|
if userId != "" && file.UserId.Hex() == userId {
|
2014-09-19 17:18:53 +08:00
|
|
|
|
return path
|
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
// 得到使用过该fileId的所有笔记NoteId
|
|
|
|
|
// 这些笔记是否有public的, 若有则ok
|
|
|
|
|
// 这些笔记(笔记本)是否有共享给我的, 若有则ok
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
noteIds := noteImageService.GetNoteIds(fileId)
|
|
|
|
|
if noteIds != nil && len(noteIds) > 0 {
|
|
|
|
|
// 这些笔记是否有public的
|
|
|
|
|
if db.Has(db.Notes, bson.M{"_id": bson.M{"$in": noteIds}, "IsBlog": true}) {
|
|
|
|
|
return path
|
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2015-01-08 21:15:56 +08:00
|
|
|
|
// 2014/12/28 修复, 如果是分享给用户组, 那就不行, 这里可以实现
|
|
|
|
|
for _, noteId := range noteIds {
|
|
|
|
|
note := noteService.GetNoteById(noteId.Hex())
|
|
|
|
|
if shareService.HasReadPerm(note.UserId.Hex(), userId, noteId.Hex()) {
|
2015-11-13 17:58:41 +08:00
|
|
|
|
return path
|
2015-01-08 21:15:56 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*
|
2015-11-13 17:58:41 +08:00
|
|
|
|
// 若有共享给我的笔记?
|
|
|
|
|
// 对该笔记可读?
|
|
|
|
|
if db.Has(db.ShareNotes, bson.M{"ToUserId": bson.ObjectIdHex(userId), "NoteId": bson.M{"$in": noteIds}}) {
|
2014-09-19 17:18:53 +08:00
|
|
|
|
return path
|
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
|
|
|
|
// 笔记本是否共享给我?
|
|
|
|
|
// 通过笔记得到笔记本
|
|
|
|
|
notes := []info.Note{}
|
|
|
|
|
db.ListByQWithFields(db.Notes, bson.M{"_id": bson.M{"$in": noteIds}}, []string{"NotebookId"}, ¬es)
|
|
|
|
|
if notes != nil && len(notes) > 0 {
|
|
|
|
|
notebookIds := make([]bson.ObjectId, len(notes))
|
|
|
|
|
for i := 0; i < len(notes); i++ {
|
|
|
|
|
notebookIds[i] = notes[i].NotebookId
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if db.Has(db.ShareNotebooks, bson.M{"ToUserId": bson.ObjectIdHex(userId), "NotebookId": bson.M{"$in": notebookIds}}) {
|
|
|
|
|
return path
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-01-08 21:15:56 +08:00
|
|
|
|
*/
|
2014-09-19 17:18:53 +08:00
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
// 可能是刚复制到owner上, 但内容又没有保存, 所以没有note->imageId的映射, 此时看是否有fromFileId
|
|
|
|
|
if file.FromFileId != "" {
|
|
|
|
|
fromFile := info.File{}
|
|
|
|
|
db.Get2(db.Files, file.FromFileId, &fromFile)
|
|
|
|
|
if fromFile.UserId.Hex() == userId {
|
|
|
|
|
return fromFile.Path
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-28 14:44:07 +08:00
|
|
|
|
// 复制共享的笔记时, 复制其中的图片到我本地
|
2014-09-19 17:18:53 +08:00
|
|
|
|
// 复制图片
|
|
|
|
|
func (this *FileService) CopyImage(userId, fileId, toUserId string) (bool, string) {
|
|
|
|
|
// 是否已经复制过了
|
|
|
|
|
file2 := info.File{}
|
|
|
|
|
db.GetByQ(db.Files, bson.M{"UserId": bson.ObjectIdHex(toUserId), "FromFileId": bson.ObjectIdHex(fileId)}, &file2)
|
|
|
|
|
if file2.FileId != "" {
|
2015-11-13 17:58:41 +08:00
|
|
|
|
return true, file2.FileId.Hex()
|
2014-09-19 17:18:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 复制之
|
|
|
|
|
file := info.File{}
|
|
|
|
|
db.GetByIdAndUserId(db.Files, fileId, userId, &file)
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
if file.FileId == "" || file.UserId.Hex() != userId {
|
|
|
|
|
return false, ""
|
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
_, ext := SplitFilename(file.Name)
|
2015-11-28 14:44:07 +08:00
|
|
|
|
guid := NewGuid()
|
|
|
|
|
newFilename := guid + ext
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2015-11-28 14:44:07 +08:00
|
|
|
|
// TODO 统一目录格式
|
|
|
|
|
// dir := "files/" + toUserId + "/images"
|
|
|
|
|
dir := "files/" + GetRandomFilePath(toUserId, guid) + "/images"
|
2014-09-19 17:18:53 +08:00
|
|
|
|
filePath := dir + "/" + newFilename
|
2015-11-28 14:44:07 +08:00
|
|
|
|
err := os.MkdirAll(revel.BasePath+dir, 0755)
|
2014-09-19 17:18:53 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return false, ""
|
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
|
|
|
|
_, err = CopyFile(revel.BasePath+"/"+file.Path, revel.BasePath+"/"+filePath)
|
2014-09-19 17:18:53 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return false, ""
|
|
|
|
|
}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
fileInfo := info.File{Name: newFilename,
|
2015-11-13 17:58:41 +08:00
|
|
|
|
Title: file.Title,
|
|
|
|
|
Path: filePath,
|
|
|
|
|
Size: file.Size,
|
2014-09-19 17:18:53 +08:00
|
|
|
|
FromFileId: file.FileId}
|
2015-11-13 17:58:41 +08:00
|
|
|
|
id := bson.NewObjectId()
|
2014-09-19 17:18:53 +08:00
|
|
|
|
fileInfo.FileId = id
|
|
|
|
|
fileId = id.Hex()
|
2015-01-08 22:08:09 +08:00
|
|
|
|
Ok, _ := this.AddImage(fileInfo, "", toUserId, false)
|
2015-11-13 17:58:41 +08:00
|
|
|
|
|
2014-09-19 17:18:53 +08:00
|
|
|
|
if Ok {
|
|
|
|
|
return Ok, id.Hex()
|
|
|
|
|
}
|
|
|
|
|
return false, ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 是否是我的文件
|
|
|
|
|
func (this *FileService) IsMyFile(userId, fileId string) bool {
|
2015-03-31 14:27:26 +08:00
|
|
|
|
// 如果有问题会panic
|
|
|
|
|
if !bson.IsObjectIdHex(fileId) || !bson.IsObjectIdHex(userId) {
|
2015-11-13 17:58:41 +08:00
|
|
|
|
return false
|
2015-03-31 14:27:26 +08:00
|
|
|
|
}
|
2014-09-19 17:18:53 +08:00
|
|
|
|
return db.Has(db.Files, bson.M{"UserId": bson.ObjectIdHex(userId), "_id": bson.ObjectIdHex(fileId)})
|
|
|
|
|
}
|