diff --git a/src/handlers/fileshdr/handlers.go b/src/handlers/fileshdr/handlers.go index 8df6f26..1694b6a 100644 --- a/src/handlers/fileshdr/handlers.go +++ b/src/handlers/fileshdr/handlers.go @@ -296,7 +296,12 @@ func (h *FileHandlers) UploadChunk(c *gin.Context) { // move the file from uploading dir to uploaded dir if uploaded+int64(wrote) == fileSize { - fsFilePath := h.FsPath(req.Path) + fsFilePath, err := h.getFSFilePath(req.Path) + if err != nil { + c.JSON(q.ErrResp(c, 500, err)) + return + } + err = h.deps.FS().Rename(tmpFilePath, fsFilePath) if err != nil { c.JSON(q.ErrResp(c, 500, fmt.Errorf("%s error: %w", req.Path, err))) @@ -318,6 +323,38 @@ func (h *FileHandlers) UploadChunk(c *gin.Context) { }) } +func (h *FileHandlers) getFSFilePath(reqPath string) (string, error) { + fsFilePath := h.FsPath(reqPath) + _, err := h.deps.FS().Stat(fsFilePath) + if err != nil { + if os.IsNotExist(err) { + return fsFilePath, nil + } + return "", err + } + + // this file exists + maxDetect := 1024 + for i := 1; i < maxDetect; i++ { + dir := path.Dir(fsFilePath) + nameAndExt := path.Base(fsFilePath) + ext := path.Ext(nameAndExt) + fileName := nameAndExt[:len(nameAndExt)-len(ext)] + + detectPath := path.Join(dir, fmt.Sprintf("%s_%d%s", fileName, i, ext)) + _, err := h.deps.FS().Stat(detectPath) + if err != nil { + if os.IsNotExist(err) { + return detectPath, nil + } else { + return "", err + } + } + } + + return "", fmt.Errorf("found more than %d duplicated files", maxDetect) +} + type UploadStatusResp struct { Path string `json:"path"` IsDir bool `json:"isDir"` diff --git a/src/server/server_files_test.go b/src/server/server_files_test.go index 0262fd7..213164e 100644 --- a/src/server/server_files_test.go +++ b/src/server/server_files_test.go @@ -149,6 +149,38 @@ func TestFileHandlers(t *testing.T) { return true } + t.Run("test uploading files with duplicated names", func(t *testing.T) { + files := map[string]string{ + "dupdir/dup_file1": "12345678", + "dupdir/dup_file2.ext": "12345678", + } + renames := map[string]string{ + "dupdir/dup_file1": "dupdir/dup_file1_1", + "dupdir/dup_file2.ext": "dupdir/dup_file2_1.ext", + } + + for filePath, content := range files { + for i := 0; i < 2; i++ { + assertUploadOK(t, filePath, content) + + err = fs.Sync() + if err != nil { + t.Fatal(err) + } + + if i == 0 { + assetDownloadOK(t, filePath, content) + } else if i == 1 { + renamedFilePath, ok := renames[filePath] + if !ok { + t.Fatal("new name not found") + } + assetDownloadOK(t, renamedFilePath, content) + } + } + } + }) + t.Run("test files APIs: Create-UploadChunk-UploadStatus-Metadata-Delete", func(t *testing.T) { for filePath, content := range map[string]string{ "path1/f1.md": "1111 1111 1111 1111", @@ -397,7 +429,7 @@ func TestFileHandlers(t *testing.T) { wg.Wait() }) - t.Run("test uploading APIs: Create, ListUploadings, DelUploading)", func(t *testing.T) { + t.Run("test uploading APIs: Create, ListUploadings, DelUploading", func(t *testing.T) { files := map[string]string{ "uploadings/path1/f1": "123456", "uploadings/path1/path2": "12345678", @@ -454,7 +486,7 @@ func TestFileHandlers(t *testing.T) { } }) - t.Run("test uploading APIs: Create, Stop, UploadChunk)", func(t *testing.T) { + t.Run("test uploading APIs: Create, Stop, UploadChunk", func(t *testing.T) { cl := client.NewFilesClient(addr) files := map[string]string{ @@ -509,7 +541,7 @@ func TestFileHandlers(t *testing.T) { } }) - t.Run("test uploading APIs: Create and UploadChunk randomly)", func(t *testing.T) { + t.Run("test uploading APIs: Create and UploadChunk randomly", func(t *testing.T) { cl := client.NewFilesClient(addr) files := map[string]string{