Feat: support apply append mode and overwrite mode for FileStream
This commit is contained in:
parent
285611baf7
commit
118d738797
16 changed files with 32 additions and 41 deletions
2
assets
2
assets
|
@ -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…
Reference in a new issue