代码拉取完成,页面将自动刷新
/*
Nging is a toolbox for webmasters
Copyright (C) 2018-present Wenhui Shen <swh@admpub.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with f program. If not, see <https://www.gnu.org/licenses/>.
*/
package file
import (
"io"
"mime"
"path/filepath"
"strings"
"time"
"github.com/coscms/go-imgparse/imgparse"
uploadClient "github.com/webx-top/client/upload"
"github.com/webx-top/db"
"github.com/webx-top/echo"
"github.com/admpub/events"
"github.com/admpub/nging/application/dbschema"
"github.com/admpub/nging/application/model/base"
"github.com/admpub/nging/application/registry/upload/table"
"github.com/admpub/nging/application/model/file/storer"
)
func NewFile(ctx echo.Context) *File {
m := &File{
NgingFile: &dbschema.NgingFile{},
base: base.New(ctx),
}
m.NgingFile.SetContext(ctx)
return m
}
type File struct {
*dbschema.NgingFile
base *base.Base
}
func (f *File) NewFile(m *dbschema.NgingFile) *File {
r := &File{
NgingFile: m,
base: f.base,
}
r.SetContext(f.base.Context)
return r
}
func (f *File) SetTableID(tableID string) table.TableInfoStorer {
if len(tableID) == 0 {
tableID = `0`
}
f.NgingFile.TableId = tableID
return f
}
func (f *File) SetTableName(table string) table.TableInfoStorer {
f.NgingFile.TableName = table
return f
}
func (f *File) SetFieldName(field string) table.TableInfoStorer {
f.NgingFile.FieldName = field
return f
}
func (f *File) TableID() string {
return f.NgingFile.TableId
}
func (f *File) TableName() string {
return f.NgingFile.TableName
}
func (f *File) FieldName() string {
return f.NgingFile.FieldName
}
func (f *File) SetByUploadResult(result *uploadClient.Result) *File {
f.Name = result.FileName
f.SavePath = result.SavePath
f.SaveName = filepath.Base(f.SavePath)
f.Ext = filepath.Ext(f.SavePath)
f.ViewUrl = result.FileURL
f.Type = result.FileType.String()
f.Size = uint64(result.FileSize)
f.Md5 = result.Md5
return f
}
func (f *File) FillData(reader io.Reader, forceReset bool, schemas ...*dbschema.NgingFile) error {
var m *dbschema.NgingFile
if len(schemas) > 0 {
m = schemas[0]
} else {
m = f.NgingFile
}
if forceReset || len(m.Mime) == 0 {
m.Mime = mime.TypeByExtension(m.Ext)
if len(f.Mime) == 0 {
f.Mime = echo.MIMEOctetStream
}
}
if m.Type == `image` {
typ := strings.TrimPrefix(m.Ext, `.`)
if typ == `jpg` {
typ = `jpeg`
}
width, height, err := imgparse.ParseRes(reader, typ)
if err != nil {
return err
}
m.Width = uint(width)
m.Height = uint(height)
m.Dpi = 0
}
return nil
}
func (f *File) Add(reader io.Reader) error {
if err := f.FillData(reader, false); err != nil {
return err
}
_, err := f.NgingFile.Add()
return err
}
func (f *File) fireDelete() error {
files := []string{f.SavePath}
thumbM := NewThumb(f.base.Context)
cnt, err := thumbM.ListByOffset(nil, nil, 0, -1, db.Cond{`file_id`: f.Id})
if err != nil {
return err
}
thumbNum := cnt()
if thumbNum > 0 {
thumbM.Use(f.Trans())
err = thumbM.Delete(nil, db.Cond{`file_id`: f.Id})
if err != nil {
return err
}
for _, thumb := range thumbM.Objects() {
files = append(files, thumb.SavePath)
}
}
err = f.base.Fire(f.OwnerType+`-file-deleted`, events.ModeSync, map[string]interface{}{
`ctx`: f.base.Context,
`data`: f.NgingFile,
`ownerID`: f.OwnerId,
})
if err != nil {
return err
}
err = f.base.Fire(`file-deleted`, events.ModeSync, map[string]interface{}{
`ctx`: f.base.Context,
`data`: f.NgingFile,
`files`: files,
})
return err
}
func (f *File) DeleteByID(id uint64, ownerType string, ownerID uint64) (err error) {
f.base.Begin()
defer func() {
f.base.End(err == nil)
}()
f.Use(f.base.Tx())
err = f.Get(nil, db.Cond{`id`: id})
if err != nil {
if err != db.ErrNoMoreRows {
return err
}
return nil
}
if f.UsedTimes > 0 && (ownerType != `user` || ownerID != 1) {
return f.base.E(`文件正在使用中,不能删除(只有创始人才能强制删除)`)
}
err = f.Delete(nil, db.Cond{`id`: id})
if err != nil {
return err
}
return f.fireDelete()
}
func (f *File) GetBySavePath(storerInfo storer.Info, savePath string) (err error) {
err = f.Get(nil, db.And(
db.Cond{`storer_name`: storerInfo.Name},
db.Cond{`storer_id`: storerInfo.ID},
db.Cond{`save_path`: savePath},
))
return
}
func (f *File) GetByViewURL(storerInfo storer.Info, viewURL string) (err error) {
err = f.Get(nil, db.And(
db.Cond{`storer_name`: storerInfo.Name},
db.Cond{`storer_id`: storerInfo.ID},
db.Cond{`view_url`: viewURL},
))
return
}
func (f *File) FnGetByMd5() func(r *uploadClient.Result) error {
fileD := &dbschema.NgingFile{}
return func(r *uploadClient.Result) error {
fileD.Reset()
err := fileD.Get(nil, db.Cond{`md5`: r.Md5})
if err != nil {
if err == db.ErrNoMoreRows {
return nil
}
return err
}
r.SavePath = fileD.SavePath
r.FileURL = fileD.ViewUrl
return table.ErrExistsFile
}
}
func (f *File) DeleteBySavePath(savePath string) (err error) {
f.base.Begin()
defer func() {
f.base.End(err == nil)
}()
f.Use(f.base.Tx())
err = f.Get(nil, db.Cond{`save_path`: savePath})
if err != nil {
if err != db.ErrNoMoreRows {
return
}
return nil
}
err = f.Delete(nil, db.Cond{`id`: f.Id})
if err != nil {
return
}
return f.fireDelete()
}
func (f *File) UpdateAvatar(project string, ownerType string, ownerID uint64) error {
f.base.Begin()
f.Use(f.base.Tx())
err := f.SetFields(nil, echo.H{
`table_id`: ownerID,
`table_name`: ownerType,
`field_name`: `avatar`,
`project`: project,
`used_times`: 1,
}, db.Cond{`id`: f.Id})
defer func() {
f.base.End(err == nil)
}()
if err != nil {
return err
}
err = f.RemoveUnusedAvatar(ownerType, f.Id)
return err
}
func (f *File) RemoveUnusedAvatar(ownerType string, excludeID uint64) error {
return f.DeleteBy(db.And(
db.Cond{`table_id`: 0},
db.Cond{`table_name`: ownerType},
db.Cond{`field_name`: `avatar`},
db.Cond{`id`: db.NotEq(excludeID)},
))
}
func (f *File) RemoveUnused(ago int64, ownerType string, ownerID uint64) error {
cond := db.NewCompounds()
cond.Add(
db.Cond{`table_id`: 0},
db.Cond{`used_times`: 0},
)
if len(ownerType) > 0 {
cond.AddKV(`owner_id`, ownerID)
cond.AddKV(`owner_type`, ownerType)
}
cond.AddKV(`created`, db.Lt(time.Now().Unix()-ago))
return f.DeleteBy(cond.And())
}
// CondByOwner 所有者条件
func (f *File) CondByOwner(ownerType string, ownerID uint64) db.Compound {
return db.And(
db.Cond{`owner_id`: ownerID},
db.Cond{`owner_type`: ownerType},
)
}
// CondByNoTarget 无宿主条件
func (f *File) CondByNoTarget() db.Compound {
return db.Cond{`table_id`: 0}
}
// UnbindTargetData 解除宿主时的设置值
func (f *File) UnbindTargetData() echo.H {
return echo.H{
`table_id`: 0,
`table_name`: ``,
`field_name`: ``,
}
}
func (f *File) DeleteBy(cond db.Compound) error {
size := 500
cnt, err := f.ListByOffset(nil, nil, 0, size, cond)
if err != nil {
return err
}
totalRows := cnt()
var start int64
for ; start < totalRows; start += int64(size) {
if start > 0 {
cnt, err = f.ListByOffset(nil, nil, 0, size, cond)
if err != nil {
return err
}
}
rows := f.Objects()
for _, fm := range rows {
f.base.Begin()
f.Use(f.base.Tx())
err = f.Delete(nil, db.Cond{`id`: fm.Id})
if err != nil {
f.base.Rollback()
return err
}
err = f.fireDelete()
f.base.End(err == nil)
if err != nil {
return err
}
}
if len(rows) < size {
break
}
}
return err
}
func (f *File) RemoveAvatar(ownerType string, ownerID int64) error {
return f.DeleteBy(db.And(
db.Cond{`table_id`: ownerID},
db.Cond{`table_name`: ownerType},
db.Cond{`field_name`: `avatar`},
))
}
func (f *File) GetAvatar() (*dbschema.NgingFile, error) {
m := &dbschema.NgingFile{}
m.CPAFrom(f.NgingFile)
err := m.Get(nil, db.Or(
db.And(
db.Cond{`table_id`: f.TableID()},
db.Cond{`table_name`: f.TableName()},
db.Cond{`field_name`: f.FieldName()},
),
db.And(
f.CondByNoTarget(),
db.Cond{`view_url`: f.ViewUrl},
),
))
return m, err
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。