File Read Utilities
Paquete: @tiendana/ngx-core/validators
Utilidades RxJS para lectura de archivos, conversión de formatos y manipulación de File objects.
Características
✅ Lectura de File y Blob como ArrayBuffer o Data URL con FileReader, expuesta como Observable
✅ Detección del tipo real por cabecera binaria (getFileType)
✅ Conversión de URLs de imagen a Data URL o a File
✅ sanitizeFileName para limpiar nombres de archivo
import {
readAsArrayBuffer,
readAsDataURL,
getFileType,
urlToDataUrl,
urlImageToFile,
sanitizeFileName
} from '@tiendana/ngx-core/validators';
Funciones Disponibles
readAsArrayBuffer
Lee un File o Blob como ArrayBuffer usando FileReader.
Firma:
function readAsArrayBuffer(blob: Blob): Observable<any>
Parámetros:
blob: File o Blob a leer
Retorna: Observable que emite el ArrayBuffer y completa. Emite un error si el valor no es un File o Blob.
Uso:
import { readAsArrayBuffer } from '@tiendana/ngx-core/validators';
onFileSelect(event: Event) {
const file = (event.target as HTMLInputElement).files?.[0];
if (file) {
readAsArrayBuffer(file).subscribe(buffer => {
console.log('Buffer length:', buffer.byteLength);
});
}
}
readAsDataURL
Lee un File o Blob como Data URL (base64).
Firma:
function readAsDataURL(blob: Blob): Observable<any>
Parámetros:
blob: File o Blob a leer
Retorna: Observable que emite el Data URL (data:...;base64,...) y completa. Emite un error si el valor no es un File o Blob.
Uso:
import { readAsDataURL } from '@tiendana/ngx-core/validators';
onImageSelect(event: Event) {
const file = (event.target as HTMLInputElement).files?.[0];
if (file) {
readAsDataURL(file).subscribe(dataUrl => {
// Usar dataUrl para preview de imagen
this.imagePreview = dataUrl as string;
});
}
}
readAsDataURL es ideal para crear previsualizaciones de imágenes antes de subirlas al servidor.
getFileType
Obtiene el tipo de un archivo leyendo su cabecera (magic numbers), no su extensión.
Firma:
function getFileType(arrayBuffer: ArrayBuffer, file?: File): string
Parámetros:
arrayBuffer: ArrayBuffer del archivo (usar conreadAsArrayBuffer)file: File opcional; solo se usa para escribir su extensión original en la consola
Retorna: 'png', 'jpeg', 'gif', 'pdf', 'xlsx' o 'unknown'
Cabeceras reconocidas (primeros 4 bytes):
| Resultado | Archivos |
|---|---|
png | PNG |
jpeg | JPEG (cabeceras ffd8ffe0, e1, e2, e3 y e8) |
gif | GIF |
pdf | |
xlsx | Cualquier contenedor ZIP: .xlsx, .docx, .zip... |
unknown | Todo lo demás |
svgyzipno se detectan nunca. Un SVG es texto (<svg ...) y su cabecera no coincide con ninguna regla; un ZIP real coincide primero con la regla dexlsx. No usesgetFileTypenirequiredFileTypepara aceptar SVG o ZIP.- Un
.docxo un.zipdevuelven'xlsx': la cabecera de todos los formatos basados en ZIP es la misma. - Escribe en la consola (
console.log) la cabecera, la extensión original y el tipo detectado en cada llamada.
Uso:
import { readAsArrayBuffer, getFileType } from '@tiendana/ngx-core/validators';
onFileSelect(event: Event) {
const file = (event.target as HTMLInputElement).files?.[0];
if (file) {
readAsArrayBuffer(file).subscribe(buffer => {
const realType = getFileType(buffer, file);
if (realType === 'unknown') {
alert('Tipo de archivo no soportado');
}
});
}
}
Para validar el tipo dentro de un formulario reactivo usa CustomValidators.requiredFileType, que se apoya en esta función.
urlToDataUrl
Convierte una URL de imagen a Data URL (base64).
Firma:
function urlToDataUrl(imageUrl: string): Observable<string | ArrayBuffer>
Parámetros:
imageUrl: URL de la imagen
Retorna: Observable que emite el Data URL y completa
Uso:
import { urlToDataUrl } from '@tiendana/ngx-core/validators';
convertRemoteImage() {
urlToDataUrl('https://example.com/image.jpg').subscribe(
dataUrl => {
console.log('Base64:', dataUrl);
// Usar dataUrl para almacenar localmente, enviar a API, etc.
},
error => console.error('Error al convertir imagen:', error)
);
}
urlToDataUrl hace un fetch a la URL. Asegúrate de que la URL sea accesible y no tenga problemas de CORS.
urlImageToFile
Convierte una URL de imagen a File object.
Firma:
function urlImageToFile(imageUrl: string): Observable<File>
Parámetros:
imageUrl: URL de la imagen
Retorna: Observable con el File object
Uso:
import { urlImageToFile } from '@tiendana/ngx-core/validators';
convertUrlToFile() {
urlImageToFile('https://example.com/photo.jpg').subscribe(
file => {
console.log('File name:', file.name);
console.log('File size:', file.size);
console.log('File type:', file.type);
// Usar file para asignar a FormControl
this.form.patchValue({ image: file });
},
error => console.error('Error al convertir a File:', error)
);
}
Características:
- Extrae el nombre del archivo de la URL
- Preserva el tipo MIME
- Retorna un File object válido para FormData o FormControl
sanitizeFileName
Elimina de un nombre de archivo todo carácter que no sea letra ASCII, dígito, espacio, guion o guion bajo, colapsa los espacios repetidos en uno y recorta los extremos.
Firma:
function sanitizeFileName(fileName: string): string
Parámetros:
fileName: Nombre de archivo a sanitizar
Retorna: Nombre sanitizado (solo a-z, A-Z, 0-9, espacio, - y _)
Uso:
import { sanitizeFileName } from '@tiendana/ngx-core/validators';
sanitizeFileName('mi archivo (copia) #1!.pdf'); // "mi archivo copia 1pdf"
sanitizeFileName('informe final '); // "informe final"
El punto también es un carácter no permitido, así que sanitizeFileName('foto.png') devuelve 'fotopng'. Sanitiza solo el nombre base y vuelve a añadir la extensión:
const dot = file.name.lastIndexOf('.');
const safe = dot > 0
? sanitizeFileName(file.name.slice(0, dot)) + file.name.slice(dot)
: sanitizeFileName(file.name);
Las letras con tilde (á, ñ) tampoco están permitidas y se eliminan.
Casos de Uso Comunes
Preview de Imagen antes de Subir
import { readAsDataURL } from '@tiendana/ngx-core/validators';
imagePreview: string | null = null;
onImageSelect(event: Event) {
const file = (event.target as HTMLInputElement).files?.[0];
if (file) {
readAsDataURL(file).subscribe(dataUrl => {
this.imagePreview = dataUrl as string;
});
}
}
<input type="file" (change)="onImageSelect($event)" accept="image/*">
@if (imagePreview) {
<img [src]="imagePreview" alt="Preview">
}
Validar Tipo Real de Archivo
import { readAsArrayBuffer, getFileType } from '@tiendana/ngx-core/validators';
validateFileType(file: File, allowedTypes: string[]) {
readAsArrayBuffer(file).subscribe(buffer => {
const realType = getFileType(buffer, file);
// Recuerda: JPEG es 'jpeg' (no 'jpg') y no se detectan 'svg' ni 'zip'
if (!allowedTypes.includes(realType)) {
alert(`Tipo de archivo no permitido. Se esperaba: ${allowedTypes.join(', ')}`);
}
});
}
// Uso
onFileSelect(event: Event) {
const file = (event.target as HTMLInputElement).files?.[0];
if (file) {
this.validateFileType(file, ['png', 'jpeg', 'pdf']);
}
}
Convertir URL Remota a File para Upload
import { urlImageToFile } from '@tiendana/ngx-core/validators';
loadRemoteImage(url: string) {
urlImageToFile(url).subscribe(file => {
// Asignar a FormControl
this.form.patchValue({ avatar: file });
// O crear FormData para upload
const formData = new FormData();
formData.append('file', file);
this.http.post('/api/upload', formData).subscribe();
});
}
Manejo de Errores
Las funciones que retornan Observables (readAsArrayBuffer, readAsDataURL, urlToDataUrl, urlImageToFile) pueden emitir errores:
import { readAsDataURL } from '@tiendana/ngx-core/validators';
import { catchError } from 'rxjs/operators';
import { of } from 'rxjs';
onFileSelect(event: Event) {
const file = (event.target as HTMLInputElement).files?.[0];
if (file) {
readAsDataURL(file).pipe(
catchError(error => {
console.error('Error al leer archivo:', error);
return of(null);
})
).subscribe(dataUrl => {
if (dataUrl) {
this.imagePreview = dataUrl as string;
}
});
}
}
Notas Importantes
- RxJS: Todas las funciones, salvo
getFileTypeysanitizeFileName(síncronas), retornan Observables, no Promises - File vs Blob: Las funciones aceptan tanto File como Blob
- CORS:
urlToDataUrlyurlImageToFilerequieren que la URL sea accesible sin restricciones CORS - Memoria: Al convertir a base64, el tamaño aumenta ~33%. Usar con archivos pequeños/medianos
- Browser support: FileReader es compatible con todos los navegadores modernos
Ver También
- CustomValidators - Validadores que usan estas utilidades
- TdnInputFile - Componente para selección de archivos