diff --git a/src/client/web/src/worker/upload.baseworker.ts b/src/client/web/src/worker/upload.baseworker.ts index 52970cc..5df2fcc 100644 --- a/src/client/web/src/worker/upload.baseworker.ts +++ b/src/client/web/src/worker/upload.baseworker.ts @@ -67,33 +67,46 @@ export class UploadWorker { }; onMsg = async (event: MessageEvent) => { - this.working = true; - const req = event.data as FileWorkerReq; + try { + this.working = true; + const req = event.data as FileWorkerReq; - switch (req.kind) { - case syncReqKind: - const syncReq = req as SyncReq; + switch (req.kind) { + case syncReqKind: + const syncReq = req as SyncReq; - if (syncReq.created) { - const status = await this.uploader.upload( - syncReq.filePath, - syncReq.file, - syncReq.uploaded - ); - await this.handleUploadStatus(status); - } else { - const status = await this.uploader.create( - syncReq.filePath, - syncReq.file - ); - await this.handleUploadStatus(status); - } - break; - default: - console.error(`unknown worker request(${JSON.stringify(req)})`); + if (syncReq.created) { + if (syncReq.file.size === 0) { + const resp: UploadInfoResp = { + kind: uploadInfoKind, + filePath: syncReq.filePath, + uploaded: 0, + state: UploadState.Ready, + err: "", + }; + this.sendEvent(resp); + } else { + const status = await this.uploader.upload( + syncReq.filePath, + syncReq.file, + syncReq.uploaded + ); + await this.handleUploadStatus(status); + } + } else { + const status = await this.uploader.create( + syncReq.filePath, + syncReq.file + ); + await this.handleUploadStatus(status); + } + break; + default: + console.error(`unknown worker request(${JSON.stringify(req)})`); + } + } finally { + this.working = false; } - - this.working = false; }; onError = (ev: ErrorEvent) => { diff --git a/src/handlers/fileshdr/handlers.go b/src/handlers/fileshdr/handlers.go index 73fadac..2856149 100644 --- a/src/handlers/fileshdr/handlers.go +++ b/src/handlers/fileshdr/handlers.go @@ -143,6 +143,55 @@ func (h *FileHandlers) Create(c *gin.Context) { return } + if req.FileSize == 0 { + err = h.deps.FS().MkdirAll(filepath.Dir(req.Path)) + if err != nil { + c.JSON(q.ErrResp(c, 500, err)) + return + } + + // TODO: limit the number of files with 0 byte + + fsFilePath, err := h.getFSFilePath(userID, req.Path) + if err != nil { + c.JSON(q.ErrResp(c, 500, err)) + return + } + + err = h.deps.FS().Create(fsFilePath) + if err != nil { + if os.IsExist(err) { + c.JSON(q.ErrResp(c, 304, fmt.Errorf("file(%s) exists", fsFilePath))) + } else { + c.JSON(q.ErrResp(c, 500, err)) + } + return + } + + msg, err := json.Marshal(Sha1Params{ + FilePath: fsFilePath, + }) + if err != nil { + c.JSON(q.ErrResp(c, 500, err)) + return + } + + err = h.deps.Workers().TryPut( + localworker.NewMsg( + h.deps.ID().Gen(), + map[string]string{localworker.MsgTypeKey: MsgTypeSha1}, + string(msg), + ), + ) + if err != nil { + c.JSON(q.ErrResp(c, 500, err)) + return + } + + c.JSON(q.Resp(200)) + return + } + tmpFilePath := q.UploadPath(userName, req.Path) locker := h.NewAutoLocker(c, lockName(tmpFilePath)) locker.Exec(func() { diff --git a/src/server/server_files_test.go b/src/server/server_files_test.go index f4c5bd3..4f59f70 100644 --- a/src/server/server_files_test.go +++ b/src/server/server_files_test.go @@ -190,6 +190,7 @@ func TestFileHandlers(t *testing.T) { t.Run("test files APIs: Create-UploadChunk-UploadStatus-Metadata-Delete", func(t *testing.T) { for filePath, content := range map[string]string{ + "qs/files/path1/empty": "", "qs/files/path1/f1.md": "1111 1111 1111 1111", "qs/files/path1/path2/f2.md": "1010 1010 1111 0000 0010", } { @@ -203,12 +204,15 @@ func TestFileHandlers(t *testing.T) { } // check uploading file - uploadFilePath := q.UploadPath(adminName, filePath) - info, err := fs.Stat(uploadFilePath) - if err != nil { - t.Fatal(err) - } else if info.Name() != filepath.Base(uploadFilePath) { - t.Fatal(info.Name(), filepath.Base(uploadFilePath)) + // empty file is not created under the uploading folder + if fileSize != 0 { + uploadFilePath := q.UploadPath(adminName, filePath) + info, err := fs.Stat(uploadFilePath) + if err != nil { + t.Fatal(err) + } else if info.Name() != filepath.Base(uploadFilePath) { + t.Fatal(info.Name(), filepath.Base(uploadFilePath)) + } } // upload a chunk @@ -250,7 +254,7 @@ func TestFileHandlers(t *testing.T) { // check uploaded file // fsFilePath := filepath.Join("0", filePath) - info, err = fs.Stat(filePath) + info, err := fs.Stat(filePath) if err != nil { t.Fatal(err) } else if info.Name() != filepath.Base(filePath) {