mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 12:17:24 +00:00
add SHA-1 hash calculation for file uploads and update related API and model structures
This commit is contained in:
104
frontend/package-lock.json
generated
104
frontend/package-lock.json
generated
@@ -8,6 +8,7 @@
|
||||
"name": "frontend",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha1-browser": "^5.2.0",
|
||||
"@marsidev/react-turnstile": "^1.1.0",
|
||||
"@tailwindcss/vite": "^4.1.5",
|
||||
"axios": "^1.9.0",
|
||||
@@ -51,6 +52,60 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-crypto/sha1-browser": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz",
|
||||
"integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==",
|
||||
"dependencies": {
|
||||
"@aws-crypto/supports-web-crypto": "^5.2.0",
|
||||
"@aws-crypto/util": "^5.2.0",
|
||||
"@aws-sdk/types": "^3.222.0",
|
||||
"@aws-sdk/util-locate-window": "^3.0.0",
|
||||
"@smithy/util-utf8": "^2.0.0",
|
||||
"tslib": "^2.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-crypto/supports-web-crypto": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
|
||||
"integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-crypto/util": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
|
||||
"integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
|
||||
"dependencies": {
|
||||
"@aws-sdk/types": "^3.222.0",
|
||||
"@smithy/util-utf8": "^2.0.0",
|
||||
"tslib": "^2.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/types": {
|
||||
"version": "3.804.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.804.0.tgz",
|
||||
"integrity": "sha512-A9qnsy9zQ8G89vrPPlNG9d1d8QcKRGqJKqwyGgS0dclJpwy6d1EWgQLIolKPl6vcFpLoe6avLOLxr+h8ur5wpg==",
|
||||
"dependencies": {
|
||||
"@smithy/types": "^4.2.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/util-locate-window": {
|
||||
"version": "3.804.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.804.0.tgz",
|
||||
"integrity": "sha512-zVoRfpmBVPodYlnMjgVjfGoEZagyRF5IPn3Uo6ZvOZp24chnW/FRstH7ESDHDDRga4z3V+ElUQHKpFDXWyBW5A==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
"version": "7.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
|
||||
@@ -1447,6 +1502,52 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@smithy/is-array-buffer": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
|
||||
"integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@smithy/types": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.2.0.tgz",
|
||||
"integrity": "sha512-7eMk09zQKCO+E/ivsjQv+fDlOupcFUCSC/L2YUPgwhvowVGWbPQHjEFcmjt7QQ4ra5lyowS92SV53Zc6XD4+fg==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@smithy/util-buffer-from": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
|
||||
"integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
|
||||
"dependencies": {
|
||||
"@smithy/is-array-buffer": "^2.2.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@smithy/util-utf8": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
|
||||
"integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
|
||||
"dependencies": {
|
||||
"@smithy/util-buffer-from": "^2.2.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/node": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.5.tgz",
|
||||
@@ -5906,8 +6007,7 @@
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"license": "0BSD",
|
||||
"optional": true
|
||||
"license": "0BSD"
|
||||
},
|
||||
"node_modules/turbo-stream": {
|
||||
"version": "2.4.0",
|
||||
|
@@ -10,6 +10,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-crypto/sha1-browser": "^5.2.0",
|
||||
"@marsidev/react-turnstile": "^1.1.0",
|
||||
"@tailwindcss/vite": "^4.1.5",
|
||||
"axios": "^1.9.0",
|
||||
|
@@ -449,11 +449,11 @@ class Network {
|
||||
}
|
||||
|
||||
async createS3Storage(
|
||||
name: string,
|
||||
endPoint: string,
|
||||
name: string,
|
||||
endPoint: string,
|
||||
accessKeyID: string,
|
||||
secretAccessKey: string,
|
||||
bucketName: string,
|
||||
secretAccessKey: string,
|
||||
bucketName: string,
|
||||
maxSizeInMB: number,
|
||||
domain: string): Promise<Response<any>> {
|
||||
try {
|
||||
@@ -520,14 +520,15 @@ class Network {
|
||||
}
|
||||
|
||||
async initFileUpload(filename: string, description: string, fileSize: number,
|
||||
resourceId: number, storageId: number): Promise<Response<UploadingFile>> {
|
||||
resourceId: number, storageId: number, sha1: string): Promise<Response<UploadingFile>> {
|
||||
try {
|
||||
const response = await axios.post(`${this.apiBaseUrl}/files/upload/init`, {
|
||||
filename,
|
||||
description,
|
||||
file_size: fileSize,
|
||||
resource_id: resourceId,
|
||||
storage_id: storageId
|
||||
storage_id: storageId,
|
||||
sha1
|
||||
});
|
||||
return response.data;
|
||||
} catch (e: any) {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import {Response} from "./models.ts";
|
||||
import {network} from "./network.ts";
|
||||
import { Sha1 } from "@aws-crypto/sha1-browser";
|
||||
import { Response } from "./models.ts";
|
||||
import { network } from "./network.ts";
|
||||
|
||||
enum UploadingStatus {
|
||||
PENDING = "pending",
|
||||
@@ -130,7 +131,7 @@ export class UploadingTask extends Listenable {
|
||||
class UploadingManager extends Listenable {
|
||||
tasks: UploadingTask[] = [];
|
||||
|
||||
onTaskStatusChanged = () => {
|
||||
onTaskStatusChanged = () => {
|
||||
if (this.tasks.length === 0) {
|
||||
return;
|
||||
}
|
||||
@@ -149,12 +150,35 @@ class UploadingManager extends Listenable {
|
||||
}
|
||||
|
||||
async addTask(file: File, resourceID: number, storageID: number, description: string, onFinished: () => void): Promise<Response<void>> {
|
||||
// Calculate SHA-1 hash of the file
|
||||
async function calculateSHA1(file: File): Promise<string> {
|
||||
const hash = new Sha1();
|
||||
const chunkSize = 4 * 1024 * 1024;
|
||||
const totalChunks = Math.ceil(file.size / chunkSize);
|
||||
for (let i = 0; i < totalChunks; i++) {
|
||||
const start = i * chunkSize;
|
||||
const end = Math.min(start + chunkSize, file.size);
|
||||
const chunk = file.slice(start, end);
|
||||
const arrayBuffer = await chunk.arrayBuffer();
|
||||
hash.update(arrayBuffer);
|
||||
}
|
||||
const hashBuffer = await hash.digest();
|
||||
const hashArray = new Uint8Array(hashBuffer);
|
||||
const hashHex = Array.from(hashArray)
|
||||
.map(byte => byte.toString(16).padStart(2, "0"))
|
||||
.join("");
|
||||
return hashHex;
|
||||
}
|
||||
|
||||
const sha1 = await calculateSHA1(file);
|
||||
|
||||
const res = await network.initFileUpload(
|
||||
file.name,
|
||||
description,
|
||||
file.size,
|
||||
resourceID,
|
||||
storageID
|
||||
storageID,
|
||||
sha1,
|
||||
)
|
||||
if (!res.success) {
|
||||
return {
|
||||
@@ -166,7 +190,7 @@ class UploadingManager extends Listenable {
|
||||
task.addListener(this.onTaskStatusChanged);
|
||||
this.tasks.push(task);
|
||||
this.onTaskStatusChanged();
|
||||
return {
|
||||
return {
|
||||
success: true,
|
||||
message: "ok",
|
||||
}
|
||||
|
Reference in New Issue
Block a user