1.Componente el-upload para subida de archivos
<template>
<div>
<!-- componente el-upload para subir archivos -->
<el-upload
ref="upload"
:action="uploadUrl"
:before-upload="prepararSubida"
:on-change="procesarCambio"
:on-success="procesarExito"
:on-error="procesarError"
:file-list="listaArchivos"
:auto-upload="false"
>
<!-- botón para seleccionar archivo -->
<el-button slot="trigger" size="small" type="primary">Seleccionar archivo</el-button>
<!-- botón para iniciar subida -->
<el-button slot="upload" size="small" type="success" @click="iniciarSubida">Iniciar subida</el-button>
</el-upload>
<!-- barra de progreso de subida -->
<el-progress :percentage="progreso"></el-progress>
</div>
</template>
data() {
return {
uploadUrl: 'https://tu-servidor/subir', // endpoint del servidor
listaArchivos: [],
progreso: 0, // progreso de subida
tamanhoFragmento: 5 * 1024 * 1024, // tamaño de cada fragmento 5MB
};
},
Cálculo de fragmentos del archivo antes de la subida``` async prepararSubida(archivo) { const totalFragmentos = Math.ceil(archivo.size / this.tamanhoFragmento)//calcular número total de fragmentos const listaFragmentos = [] //almacenar todos los fragmentos // dividir el archivo en múltiples bloques for(let i = 0; i < totalFragmentos; i++){ const inicio = i * this.tamanhoFragmento // posición de inicio del fragmento actual const fin = Math.min(inicio + this.tamanhoFragmento, archivo.size) // posición de fin del fragmento actual listaFragmentos.push(archivo.slice(inicio, fin)) //extraer la parte del archivo desde inicio hasta fin y devolver un nuevo objeto Blob } //agregar fragmentos a listaArchivos para perparar subida this.listaFragmentos = listaFragmentos.map((frgamento, indice) => { return { raw: fragmento, // fragmento actual nombre: archivo.name, // nombre del archivo indiceFragmento: indice, // índice del fragmento actual totalFragmentos: totalFragmentos,// total de fragmentos hashArchivo: await this.calcularHashArchivo(archivo),//identificador único del archivo
} }) return false }
Cifrado```
// calcular el valor hash del archivo (identificador único) npm install spark-md5 --save
calcularHashArchivo(archivo) {
const spark = new SparkMD5.ArrayBuffer(); // usar SparkMD5 para calcular el hash
const lector = new FileReader();
return new Promise((resolve, reject) => {
lector.onload = function(e) {
spark.append(e.target.result);
resolve(spark.end()); // devolver el hash calculado
};
lector.onerror = function(error) {
reject(error);
};
lector.readAsArrayBuffer(archivo); // leer contenido del archivo
});
},
Al hacer clic en iniciar subida``` iniciarSubida(){ this.listaFragmentos.forEach((objArchivo) => { this.subirFragmento(objArchivo) //subir cada fragmento }) }
subirFragmento(objArchivo){
// verificar si el fragmento actual ya fue subido
this.obtenerFragmentosSubidos(objArchivo.nombre).then(fragmentosSubidos => {
if (fragmentosSubidos.includes(objArchivo.indiceFragmento)) {
console.log(`Fragmento ${objArchivo.indiceFragmento} ya fue subido, omitir`);
return; // si el fragmento ya fue subido, omitir la subida
}
// subir fragmentos no-subidos
const formData = new FormData(); // crear instancia FormData para preparar datos
formData.append('file', objArchivo.raw); // fragmento actual
formData.append('chunkIndex', objArchivo.indiceFragmento); // índice del fragmento actual
formData.append('totalChunks', objArchivo.totalFragmentos); // total de fragmentos
formData.append('fileName', objArchivo.nombre); // nombre del archivo
formData.append('fileHash', objArchivo.hashArchivo); // identificador único del archivo (hash)
// usar fetch para realizar solicitud de subida
this.subirArchivo(formData, objArchivo)
.then(respuesta => {
this.procesarExito(objArchivo, respuesta); // al subir exitosamente procesar
})
.catch(error => {
this.procesarError(objArchivo, error); // al fallar la subida procesar
});
});
}
Obtener índices de fragmentos subidos```
obtenerFragmentosSubidos(nombreArchivo) {
return fetch(`https://tu-servidor/obtenerFragmentosSubidos?fileName=${nombreArchivo}`)
.then(respuesta => respuesta.json())
.then(datos => datos.fragmentosSubidos); // devolver array de índices de fragmentos subidos
},
Llamada a la interfaz de subida``` subirArchivo(formData, objArchivo) { return new Promise((resolve, reject) => { fetch(this.uploadUrl, { method: 'POST', headers: this.encabezados, body: formData, }) .then(respuesta => respuesta.json()) // parsear respuesta JSON .then(datos => { if (datos.estado === 'exito') { this.actualizarFragmentosSubidos(objArchivo.nombre, objArchivo.indiceFragmento); // actualizar fragmentos subidos resolve(datos); // al subir exitosamente, devolver datos de éxito } else { reject(new Error('Error en la subida')); // al fallar la subida, devolver error } }) .catch(err => { reject(err); // al fallar la solicitud, devolver error }); }); },
// actualizar índice de fragmentos subidos
actualizarFragmentosSubidos(nombreArchivo, indiceFragmento) {
let fragmentosSubidos = JSON.parse(localStorage.getItem(nombreArchivo)) || [];
if (!fragmentosSubidos.includes(indiceFragmento)) {
fragmentosSubidos.push(indiceFragmento);
}
localStorage.setItem(nombreArchivo, JSON.stringify(fragmentosSubidos)); // guardar en localStorage
},