diff --git a/pkg/filesystem/driver/cos/handller.go b/pkg/filesystem/driver/cos/handller.go index e688182..7b81b6f 100644 --- a/pkg/filesystem/driver/cos/handller.go +++ b/pkg/filesystem/driver/cos/handller.go @@ -50,7 +50,27 @@ func (handler Driver) Put(ctx context.Context, file io.ReadCloser, dst string, s // Delete 删除一个或多个文件, // 返回未删除的文件,及遇到的最后一个错误 func (handler Driver) Delete(ctx context.Context, files []string) ([]string, error) { - return []string{}, errors.New("未实现") + obs := []cossdk.Object{} + for _, v := range files { + obs = append(obs, cossdk.Object{Key: v}) + } + opt := &cossdk.ObjectDeleteMultiOptions{ + Objects: obs, + Quiet: true, + } + + res, _, err := handler.Client.Object.DeleteMulti(context.Background(), opt) + if err != nil { + return files, err + } + + // 整理删除结果 + failed := make([]string, 0, len(files)) + for _, v := range res.Errors { + failed = append(failed, v.Key) + } + + return failed, errors.New("删除失败") } // Thumb 获取文件缩略图 diff --git a/pkg/filesystem/driver/onedrive/api.go b/pkg/filesystem/driver/onedrive/api.go index 9ce6fed..6a6ec7c 100644 --- a/pkg/filesystem/driver/onedrive/api.go +++ b/pkg/filesystem/driver/onedrive/api.go @@ -1,6 +1,7 @@ package onedrive import ( + "bytes" "context" "encoding/json" "errors" @@ -9,7 +10,6 @@ import ( "github.com/HFO4/cloudreve/pkg/cache" "github.com/HFO4/cloudreve/pkg/request" "github.com/HFO4/cloudreve/pkg/util" - "github.com/cloudflare/cfssl/log" "io" "io/ioutil" "net/http" @@ -142,7 +142,7 @@ func (client *Client) GetUploadSessionStatus(ctx context.Context, uploadURL stri // UploadChunk 上传分片 func (client *Client) UploadChunk(ctx context.Context, uploadURL string, chunk *Chunk) (*UploadSessionResponse, error) { res, err := client.request( - ctx, "PUT", uploadURL, chunk.Reader, + ctx, "PUT", uploadURL, bytes.NewReader(chunk.Data[0:chunk.ChunkSize]), request.WithContentLength(int64(chunk.ChunkSize)), request.WithHeader(http.Header{ "Content-Range": {fmt.Sprintf("bytes %d-%d/%d", chunk.Offset, chunk.Offset+chunk.ChunkSize-1, chunk.Total)}, @@ -153,7 +153,7 @@ func (client *Client) UploadChunk(ctx context.Context, uploadURL string, chunk * // 如果重试次数小于限制,5秒后重试 if chunk.Retried < model.GetIntSetting("onedrive_chunk_retries", 1) { chunk.Retried++ - log.Debug("分片偏移%d上传失败,5秒钟后重试", chunk.Offset) + util.Log().Debug("分片偏移%d上传失败,5秒钟后重试", chunk.Offset) time.Sleep(time.Duration(5) * time.Second) return client.UploadChunk(ctx, uploadURL, chunk) } @@ -196,6 +196,9 @@ func (client *Client) Upload(ctx context.Context, dst string, size int, file io. if size%int(ChunkSize) != 0 { chunkNum++ } + + chunkData := make([]byte, ChunkSize) + for i := 0; i < chunkNum; i++ { select { case <-ctx.Done(): @@ -207,17 +210,23 @@ func (client *Client) Upload(ctx context.Context, dst string, size int, file io. if size-offset < chunkSize { chunkSize = size - offset } + + // 因为后面需要错误重试,这里要把分片内容读到内存中 + chunkContent := chunkData[:chunkSize] + _, err := io.ReadFull(file, chunkContent) + if err != nil { + return err + } + chunk := Chunk{ Offset: offset, ChunkSize: chunkSize, Total: size, - Reader: &io.LimitedReader{ - R: file, - N: int64(chunkSize), - }, + Data: chunkContent, } + // 上传 - _, err := client.UploadChunk(ctx, uploadURL, &chunk) + _, err = client.UploadChunk(ctx, uploadURL, &chunk) if err != nil { return err } diff --git a/pkg/filesystem/driver/onedrive/api_test.go b/pkg/filesystem/driver/onedrive/api_test.go index e3511ac..a1295d2 100644 --- a/pkg/filesystem/driver/onedrive/api_test.go +++ b/pkg/filesystem/driver/onedrive/api_test.go @@ -388,7 +388,7 @@ func TestClient_UploadChunk(t *testing.T) { ChunkSize: 10, Total: 100, Retried: 0, - Reader: strings.NewReader("1231312"), + Data: strings.NewReader("1231312"), }) clientMock.AssertExpectations(t) asserts.NoError(err) @@ -418,7 +418,7 @@ func TestClient_UploadChunk(t *testing.T) { ChunkSize: 10, Total: 100, Retried: 0, - Reader: strings.NewReader("1231312"), + Data: strings.NewReader("1231312"), }) clientMock.AssertExpectations(t) asserts.Error(err) @@ -448,7 +448,7 @@ func TestClient_UploadChunk(t *testing.T) { ChunkSize: 5, Total: 100, Retried: 0, - Reader: strings.NewReader("1231312"), + Data: strings.NewReader("1231312"), }) clientMock.AssertExpectations(t) asserts.NoError(err) @@ -483,7 +483,7 @@ func TestClient_UploadChunk(t *testing.T) { ChunkSize: 5, Total: 100, Retried: 0, - Reader: strings.NewReader("1231312"), + Data: strings.NewReader("1231312"), } res, err := client.UploadChunk(context.Background(), "http://dev.com", chunk) clientMock.AssertExpectations(t) diff --git a/pkg/filesystem/driver/onedrive/types.go b/pkg/filesystem/driver/onedrive/types.go index e3e644d..3e016e4 100644 --- a/pkg/filesystem/driver/onedrive/types.go +++ b/pkg/filesystem/driver/onedrive/types.go @@ -2,7 +2,6 @@ package onedrive import ( "encoding/gob" - "io" "net/url" "sync" ) @@ -90,7 +89,7 @@ type Chunk struct { ChunkSize int Total int Retried int - Reader io.Reader + Data []byte } // oauthEndpoint OAuth接口地址 diff --git a/pkg/filesystem/upload.go b/pkg/filesystem/upload.go index 9e84868..c4c880e 100644 --- a/pkg/filesystem/upload.go +++ b/pkg/filesystem/upload.go @@ -43,6 +43,7 @@ func (fs *FileSystem) Upload(ctx context.Context, file FileHeader) (err error) { // 保存文件 err = fs.Handler.Put(ctx, file, savePath, file.GetSize()) if err != nil { + fs.Trigger(ctx, "AfterUploadFailed") return err } diff --git a/pkg/webdav/if.go b/pkg/webdav/if.go index 416e81c..a98dac2 100644 --- a/pkg/webdav/if.go +++ b/pkg/webdav/if.go @@ -131,7 +131,7 @@ const ( ) func lex(s string) (tokenType rune, tokenStr string, remaining string) { - // The net/textproto Reader that parses the HTTP header will collapse + // The net/textproto Data that parses the HTTP header will collapse // Linear White Space that spans multiple "\r\n" lines to a single " ", // so we don't need to look for '\r' or '\n'. for len(s) > 0 && (s[0] == '\t' || s[0] == ' ') { diff --git a/pkg/webdav/webdav.go b/pkg/webdav/webdav.go index 015723c..d171b84 100644 --- a/pkg/webdav/webdav.go +++ b/pkg/webdav/webdav.go @@ -346,6 +346,7 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request, fs *filesyst fs.Use("AfterUpload", filesystem.GenericAfterUpload) fs.Use("AfterValidateFailed", filesystem.HookDeleteTempFile) fs.Use("AfterValidateFailed", filesystem.HookGiveBackCapacity) + fs.Use("AfterUploadFailed", filesystem.HookGiveBackCapacity) } // 执行上传 diff --git a/routers/controllers/file.go b/routers/controllers/file.go index c74fda2..87a22e1 100644 --- a/routers/controllers/file.go +++ b/routers/controllers/file.go @@ -288,6 +288,7 @@ func FileUploadStream(c *gin.Context) { fs.Use("AfterUpload", filesystem.GenericAfterUpload) fs.Use("AfterValidateFailed", filesystem.HookDeleteTempFile) fs.Use("AfterValidateFailed", filesystem.HookGiveBackCapacity) + fs.Use("AfterUploadFailed", filesystem.HookGiveBackCapacity) // 执行上传 uploadCtx := context.WithValue(ctx, fsctx.GinCtx, c)