diff --git a/handler/user/user.go b/handler/user/user.go index 536b87f..fd3a9ce 100644 --- a/handler/user/user.go +++ b/handler/user/user.go @@ -45,6 +45,8 @@ type ActionUploadNewFile struct { Name string `json:"name"` Size uint64 `json:"size"` Chunk uint64 `json:"chunk"` + StartHash string `json:"startHash"` + EndHash string `json:"endHash"` RequestID string `json:"requestID"` } @@ -127,7 +129,7 @@ func handlerWS(conn *websocket.Conn, userSession types.User) { err = json.Unmarshal(message, &action) if err != nil { app.Server.Logger.Error("Error unmarshalling WebsocketAction:", err) - sendErrorResponse(conn, action.Action) + sendErrorResponse(conn, action.Action, "Internal Server Error") continue } @@ -137,7 +139,7 @@ func handlerWS(conn *websocket.Conn, userSession types.User) { err = json.Unmarshal(message, &uploadNewFile) if err != nil { app.Server.Logger.Error("Error unmarshalling ActionUploadNewFile:", err) - sendErrorResponse(conn, action.Action) + sendErrorResponse(conn, action.Action, "Internal Server Error") continue } var file *models.File @@ -149,12 +151,14 @@ func handlerWS(conn *websocket.Conn, userSession types.User) { OwnerID: userSession.UserID, Name: uploadNewFile.Name, Size: uploadNewFile.Size, + StartHash: uploadNewFile.StartHash, + EndHash: uploadNewFile.EndHash, TotalChunk: uploadNewFile.Chunk, Downloaded: 0, } err := app.Server.Database.CreateFile(&newFile) if err != nil { - sendErrorResponse(conn, action.Action) + sendErrorResponse(conn, action.Action, "Error Creating File") continue } fileData := &types.FileWithDetail{ @@ -179,10 +183,14 @@ func handlerWS(conn *websocket.Conn, userSession types.User) { sendSuccessResponseWithID(conn, action.Action, fileData, uploadNewFile.RequestID) continue } else { - sendErrorResponse(conn, action.Action) + sendErrorResponse(conn, action.Action, "Unknown error") continue } } + if uploadNewFile.StartHash != file.StartHash || uploadNewFile.EndHash != file.EndHash { + sendErrorResponse(conn, action.Action, "File Is Different") + continue + } fileData := &types.FileWithDetail{ ID: file.ID, OwnerID: file.OwnerID, @@ -213,10 +221,11 @@ func handlerWS(conn *websocket.Conn, userSession types.User) { } } -func sendErrorResponse(conn *websocket.Conn, action ActionType) { +func sendErrorResponse(conn *websocket.Conn, action ActionType, message string) { response := map[string]interface{}{ - "action": action, - "status": "error", + "action": action, + "status": "error", + "message": message, } marshal, err := json.Marshal(response) if err != nil { diff --git a/public/main.js b/public/main.js index 8495404..d6dcced 100644 --- a/public/main.js +++ b/public/main.js @@ -9,14 +9,25 @@ if (!window.mySocket) { window.mySocket.onmessage = async function(event) { try { const data = JSON.parse(event.data); - if (data.action === "UploadNewFile") { - if (data.response.Done === false) { - const file = window.fileIdMap[data.responseID]; - addNewUploadElement(file); - const fileChunks = await splitFile(file, file.chunkSize); - await uploadChunks(file.name, file.size, fileChunks, data.response.Chunk, data.response.ID); + if (data.status === "error") { + if (data.message === "File Is Different") { + ChangeModal("Error", "A file with the same name already exists but has a different hash value. This may indicate that the file is different, despite having the same name. Please verify the file or consider renaming it before proceeding.") + toggleModal(); } else { - alert("File already uploaded."); + ChangeModal("Error", "There was an issue with your upload. Please try again later or contact support if the problem persists.") + toggleModal(); + } + } else { + if (data.action === "UploadNewFile") { + if (data.response.Done === false) { + const file = window.fileIdMap[data.responseID]; + addNewUploadElement(file); + const fileChunks = await splitFile(file, file.chunkSize); + await uploadChunks(file.name, file.size, fileChunks, data.response.Chunk, data.response.ID); + } else { + ChangeModal("Error", "File already uploaded.") + toggleModal(); + } } } } catch (error) { @@ -44,11 +55,17 @@ async function handleFile(file){ const chunkSize = 2 * 1024 * 1024; const chunks = Math.ceil(file.size / chunkSize); const fileId = generateUniqueId(); + const startChunk = await file.slice(0, chunkSize).arrayBuffer(); + const endChunk = await file.slice((chunks-1) * chunkSize, file.size).arrayBuffer(); + const startChunkHash = await hash(startChunk) + const endChunkHash = await hash(endChunk) const data = JSON.stringify({ "action": "UploadNewFile", "name": file.name, "size": file.size, "chunk": chunks, + "startHash": startChunkHash, + "endHash": endChunkHash, "requestID": fileId, }); file.chunkSize = chunkSize; @@ -133,12 +150,22 @@ async function splitFile(file, chunkSize) { const start = i * chunkSize; const end = Math.min(fileSize, start + chunkSize); const chunk = file.slice(start, end); + chunk.hash = "test" fileChunks.push(chunk); } return fileChunks; } +async function hash(arrayBuffer) { + const hashBuffer = await crypto.subtle.digest('SHA-256', arrayBuffer); + const hashArray = Array.from(new Uint8Array(hashBuffer)); + const hashHex = hashArray + .map((bytes) => bytes.toString(16).padStart(2, '0')) + .join(''); + return hashHex; +} + async function uploadChunks(name, size, chunks, chunkArray, FileID) { let byteUploaded = 0 let progress1 = document.getElementById(`progress-${name}-1`); diff --git a/types/models/models.go b/types/models/models.go index 6fb1fb7..68978bc 100644 --- a/types/models/models.go +++ b/types/models/models.go @@ -16,6 +16,8 @@ type File struct { Name string `gorm:"type:text;not null"` Size uint64 `gorm:"not null"` TotalChunk uint64 `gorm:"not null"` + StartHash string `gorm:"type:text;not null"` + EndHash string `gorm:"type:text;not null"` Downloaded uint64 `gorm:"not null;default:0"` Owner *User `gorm:"foreignKey:OwnerID;constraint:OnDelete:CASCADE;"` }