mcwl-pc/app/composables/useFileHash.ts

57 lines
1.5 KiB
TypeScript

// composables/useFileHash.ts
import { ref } from 'vue'
export const useFileHash = () => {
const isCalculating = ref(false)
const error = ref<Error | null>(null)
const calculateHash = async (file: File): Promise<string> => {
try {
if (!process.client) {
throw new Error('This function can only run in browser')
}
if (!window.crypto || !window.crypto.subtle) {
throw new Error('Crypto API is not supported in this browser')
}
isCalculating.value = true
return await new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsArrayBuffer(file)
reader.onload = async (event) => {
try {
const buffer = event.target?.result as ArrayBuffer
if (!buffer) {
throw new Error('Failed to read file buffer')
}
const hashBuffer = await window.crypto.subtle.digest('SHA-256', buffer)
const hashArray = Array.from(new Uint8Array(hashBuffer))
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
resolve(hashHex)
} catch (err) {
reject(err)
}
}
reader.onerror = () => {
reject(new Error('Failed to read file'))
}
})
} catch (err) {
error.value = err as Error
throw err
} finally {
isCalculating.value = false
}
}
return {
calculateHash,
isCalculating,
error
}
}