Add hash check for file upload
This commit is contained in:
@ -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 {
|
||||
|
@ -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`);
|
||||
|
@ -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;"`
|
||||
}
|
||||
|
Reference in New Issue
Block a user