Feat: support apply append mode and overwrite mode for FileStream

pull/1107/head
HFO4 2 years ago
parent 285611baf7
commit 118d738797

@ -1 +1 @@
Subproject commit b90a49ba5d809e3042bce801ac28fb7cde74c878
Subproject commit eb3f32922ab9cd2f9fbef4860b93fec759a7054d

@ -308,7 +308,7 @@ func (fs *FileSystem) Decompress(ctx context.Context, src, dst string) error {
Size: uint64(size),
Name: path.Base(dst),
VirtualPath: path.Dir(dst),
Mode: fsctx.Create,
Mode: 0,
})
fileStream.Close()
if err != nil {

@ -93,7 +93,7 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
dst := util.RelativePath(filepath.FromSlash(fileInfo.SavePath))
// 如果非 Overwrite则检查是否有重名冲突
if fileInfo.Mode == fsctx.Create {
if fileInfo.Mode&fsctx.Overwrite != fsctx.Overwrite {
if util.Exists(dst) {
util.Log().Warning("物理同名文件已存在或不可用: %s", dst)
return errors.New("物理同名文件已存在或不可用")
@ -115,21 +115,21 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
err error
)
if fileInfo.Mode == fsctx.Append {
// 如果是追加模式,则直接打开文件
out, err = os.OpenFile(dst, os.O_APPEND|os.O_CREATE|os.O_WRONLY, Perm)
openMode := os.O_CREATE | os.O_RDWR
if fileInfo.Mode&fsctx.Append == fsctx.Append {
openMode |= os.O_APPEND
} else {
// 创建或覆盖目标文件
out, err = os.Create(dst)
openMode |= os.O_TRUNC
}
out, err = os.OpenFile(dst, openMode, Perm)
if err != nil {
util.Log().Warning("无法打开或创建文件,%s", err)
return err
}
defer out.Close()
if fileInfo.Mode == fsctx.Append {
if fileInfo.Mode&fsctx.Append == fsctx.Append {
stat, err := out.Stat()
if err != nil {
util.Log().Warning("无法读取文件信息,%s", err)
@ -144,7 +144,7 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
return fmt.Errorf("覆盖分片时发生错误: %w", err)
}
out, err = os.OpenFile(dst, os.O_APPEND|os.O_CREATE|os.O_WRONLY, Perm)
out, err = os.OpenFile(dst, openMode, Perm)
defer out.Close()
if err != nil {
util.Log().Warning("无法打开或创建文件,%s", err)

@ -260,9 +260,9 @@ func (client *Client) UploadChunk(ctx context.Context, uploadURL string, chunk *
func (client *Client) Upload(ctx context.Context, file fsctx.FileHeader) error {
fileInfo := file.Info()
// 决定是否覆盖文件
overwrite := "replace"
if fileInfo.Mode != fsctx.Create {
overwrite = "fail"
overwrite := "fail"
if fileInfo.Mode&fsctx.Overwrite == fsctx.Overwrite {
overwrite = "replace"
}
size := int(fileInfo.Size)

@ -237,11 +237,7 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
credentialTTL := model.GetIntSetting("upload_credential_timeout", 3600)
// 是否允许覆盖
overwrite := true
if fileInfo.Mode == fsctx.Create {
overwrite = false
}
overwrite := fileInfo.Mode&fsctx.Overwrite == fsctx.Overwrite
options := []oss.Option{
oss.Expires(time.Now().Add(time.Duration(credentialTTL) * time.Second)),
oss.ForbidOverWrite(!overwrite),

@ -173,9 +173,9 @@ func (handler Driver) Put(ctx context.Context, file fsctx.FileHeader) error {
fileName := url.QueryEscape(path.Base(fileInfo.SavePath))
// 决定是否要禁用文件覆盖
overwrite := "true"
if fileInfo.Mode != fsctx.Create {
overwrite = "false"
overwrite := "false"
if fileInfo.Mode&fsctx.Overwrite == fsctx.Overwrite {
overwrite = "true"
}
// 上传文件

@ -8,11 +8,10 @@ import (
type WriteMode int
const (
Overwrite WriteMode = iota
Overwrite WriteMode = 0x00001
// Append 只适用于本地策略
Append
Create
Nop
Append = 0x00002
Nop = 0x00004
)
type UploadTaskInfo struct {

@ -151,6 +151,7 @@ func HookCleanFileContent(ctx context.Context, fs *FileSystem, file fsctx.FileHe
File: ioutil.NopCloser(strings.NewReader("")),
SavePath: file.Info().SavePath,
Size: 0,
Model: fsctx.Overwrite,
})
}

@ -51,7 +51,7 @@ func (fs *FileSystem) Upload(ctx context.Context, file *fsctx.FileStream) (err e
go fs.CancelUpload(ctx, savePath, file)
// 保存文件
if file.Mode != fsctx.Nop {
if file.Mode&fsctx.Nop != fsctx.Nop {
err = fs.Handler.Put(ctx, file)
if err != nil {
fs.Trigger(ctx, "AfterUploadFailed", file)
@ -73,7 +73,7 @@ func (fs *FileSystem) Upload(ctx context.Context, file *fsctx.FileStream) (err e
return err
}
if file.Mode == fsctx.Create {
if file.Mode&fsctx.Overwrite == 0 {
fileInfo := file.Info()
util.Log().Info(
"新文件PUT:%s , 大小:%d, 上传者:%s",

@ -7,7 +7,6 @@ import (
model "github.com/cloudreve/Cloudreve/v3/models"
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem"
"github.com/cloudreve/Cloudreve/v3/pkg/filesystem/fsctx"
"github.com/cloudreve/Cloudreve/v3/pkg/util"
)
@ -107,7 +106,7 @@ func (job *CompressTask) Do() {
job.TaskModel.SetProgress(TransferringProgress)
// 上传文件
err = fs.UploadFromPath(ctx, zipFile, job.TaskProps.Dst, true, fsctx.Create)
err = fs.UploadFromPath(ctx, zipFile, job.TaskProps.Dst, true, 0)
if err != nil {
job.SetErrorMsg(err.Error())
return

@ -119,7 +119,6 @@ func (job *TransferTask) Do() {
err = fs.Handler.Put(context.Background(), &fsctx.FileStream{
File: file,
Mode: fsctx.Create,
SavePath: job.Req.Dst,
Size: uint64(size),
})

@ -123,11 +123,10 @@ func (job *TransferTask) Do() {
Size: job.TaskProps.SrcSizes[file],
Name: path.Base(dst),
VirtualPath: path.Dir(dst),
Mode: fsctx.Create,
})
} else {
// 主机节点中转
err = fs.UploadFromPath(context.Background(), file, dst, true, fsctx.Create)
err = fs.UploadFromPath(context.Background(), file, dst, true, 0)
}
if err != nil {

@ -355,6 +355,7 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request, fs *filesyst
fs.Use("AfterValidateFailed", filesystem.HookCleanFileContent)
fs.Use("AfterValidateFailed", filesystem.HookClearFileSize)
ctx = context.WithValue(ctx, fsctx.FileModelCtx, *originFile)
fileData.Mode |= fsctx.Overwrite
} else {
// 给文件系统分配钩子
fs.Use("BeforeUpload", filesystem.HookValidateFile)
@ -364,9 +365,6 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request, fs *filesyst
fs.Use("AfterUpload", filesystem.GenericAfterUpload)
fs.Use("AfterUpload", filesystem.HookGenerateThumb)
fs.Use("AfterValidateFailed", filesystem.HookDeleteTempFile)
// 禁止覆盖
fileData.Mode = fsctx.Create
}
// 执行上传

@ -73,10 +73,10 @@ func SlaveUpload(c *gin.Context) {
fs.Use("AfterUpload", filesystem.SlaveAfterUpload)
fs.Use("AfterValidateFailed", filesystem.HookDeleteTempFile)
// 是否允许覆盖
if c.Request.Header.Get("X-Cr-Overwrite") == "false" {
fileData.Mode = fsctx.Create
}
//// 是否允许覆盖
//if c.Request.Header.Get("X-Cr-Overwrite") == "false" {
// fileData.Mode = fsctx.Create
//}
// 执行上传
err = fs.Upload(ctx, &fileData)

@ -65,7 +65,6 @@ func (service *SingleFileService) Create(c *gin.Context) serializer.Response {
Size: 0,
VirtualPath: path.Dir(service.Path),
Name: path.Base(service.Path),
Mode: fsctx.Create,
})
if err != nil {
return serializer.Err(serializer.CodeUploadFailed, err.Error(), err)
@ -375,6 +374,7 @@ func (service *FileIDService) PutContent(ctx context.Context, c *gin.Context) se
MIMEType: c.Request.Header.Get("Content-Type"),
File: c.Request.Body,
Size: fileSize,
Model: fsctx.Overwrite,
}
// 创建文件系统

@ -148,7 +148,7 @@ func processChunkUpload(ctx context.Context, c *gin.Context, fs *filesystem.File
Name: session.Name,
VirtualPath: session.VirtualPath,
SavePath: session.SavePath,
Mode: fsctx.Append,
Mode: fsctx.Append | fsctx.Overwrite,
AppendStart: chunkSize * uint64(index),
Model: file,
LastModified: session.LastModified,

Loading…
Cancel
Save