Overview
TheFileStorageService manages the storage and retrieval of files in the local filesystem. It creates organized folder structures per person, calculates file metadata (SHA-256, size, path), and provides secure access to stored documents.
Package: co.edu.unbosque.ccdigital.service
Key Features:
- Person-based folder organization
- Automatic SHA-256 hash calculation
- File metadata tracking (size, path, original name)
- Path normalization across operating systems
- Security validation for file access
Configuration
The service uses theFileStorageProperties class to read configuration:
CCDIGITAL_FS_BASE_PATH
The application requires read/write permissions on the configured base path.
Person Folder Structure
Folder Naming Convention
Personal folders are created using a normalized combination of last name and first name: Rules:- Concatenates
lastName+firstName - Removes all spaces
- Normalizes to ASCII (removes accents/diacritics)
- Keeps only alphanumeric characters
María José González → GonzalezMariaJose
Storage Path Format
Files are stored with relative paths normalized to forward slashes (/):
Core Methods
ensurePersonFolder(Person person)
ensurePersonFolder(Person person)
Creates the person’s folder if it doesn’t exist.Parameters:
person- Person entity with name information
Path - Absolute path to the person’s folderThrows: IllegalStateException if folder creation failsstorePersonFile(Person person, MultipartFile file)
storePersonFile(Person person, MultipartFile file)
Stores a file on disk and calculates metadata.Behavior:
- Generates filename if
originalFilenameis empty:upload-{timestamp} - Writes file with
REPLACE_EXISTINGpolicy - Calculates SHA-256 hash after storage
- Returns structured metadata in
StoredFileInfo
person- Person entity (folder owner)file- Multipart file from HTTP request
StoredFileInfo - Contains:relativePath- Path relative to basePath (using/)size- File size in bytessha256- SHA-256 hash (hex, lowercase)originalName- Original filename
IllegalStateException on storage errorbuildRelativePath(Person person, String filename)
buildRelativePath(Person person, String filename)
Builds a relative path for a file without storing it.Parameters:
person- Person entityfilename- Target filename
String - Relative path with / separatorsUsage:resolvePath(FileRecord fileRecord)
resolvePath(FileRecord fileRecord)
Resolves the absolute path from a
FileRecord’s stored relative path.Parameters:fileRecord- Entity containingstoragePathfield
Path - Absolute, normalized path to the fileThrows: IllegalStateException if storagePath is emptyUsage:This method normalizes Windows-style backslashes (
\\) to forward slashes for cross-platform compatibility.loadAsResource(FileRecord fileRecord)
loadAsResource(FileRecord fileRecord)
Loads a file as a Spring
Resource for download/viewing.Parameters:fileRecord- Entity with file metadata
Resource - FileSystemResource ready for HTTP responseUsage:FileRecord Entity
Files are tracked in thefiles table with the following structure:
| Field | Type | Description |
|---|---|---|
id | Long | Primary key |
document_id | Long | FK to documents (document definition) |
person_document_id | Long | FK to person_documents |
original_name | String(300) | Original filename with extension |
mime_type | String(150) | File MIME type |
byte_size | Long | File size in bytes |
sha256_hex | String(64) | SHA-256 hash (hexadecimal) |
stored_as | Enum | Storage strategy: PATH, BLOB, S3 |
file_path | String(800) | Relative path (for PATH strategy) |
content | BLOB | Binary content (for BLOB strategy) |
version | Integer | File version (auto-incremented) |
uploaded_by_user | Long | User ID who uploaded |
uploaded_at | Timestamp | Upload timestamp (DB-managed) |
- PATH (default): File stored on filesystem, path in
file_path - BLOB: File stored in database
contentfield - S3: File stored in S3 (path in
file_path)
Security Considerations
Path Traversal Prevention
The service usesPath.normalize() and validates that resolved paths remain within the base path:
SHA-256 Hash Calculation
The service calculates SHA-256 hashes for file integrity verification: Method:calculateSha256(Path file)
Process:
- Opens file input stream
- Creates SHA-256 MessageDigest
- Reads file in 8KB chunks
- Updates digest for each chunk
- Returns hex-encoded hash (lowercase)
a3f5d...b2c1e (64 characters)
Hashes are calculated after the file is written to disk to ensure the stored file’s integrity.
StoredFileInfo DTO
Returned bystorePersonFile() with file metadata:
Related Services
- PersonService - Creates persons and triggers folder creation (FileStorageService:80)
- SignedUrlService - Generates secure URLs for file access
- PersonDocumentService - Links files to person documents
Error Handling
| Exception | Cause | Solution |
|---|---|---|
IllegalStateException: "No se pudo crear la carpeta de la persona" | Filesystem permissions issue | Check write permissions on base path |
IllegalStateException: "storagePath vacío para FileRecord" | FileRecord has no path | Ensure storagePath is set before resolving |
IllegalStateException: "Error calculando hash SHA-256" | File read error or algorithm unavailable | Check file existence and Java crypto support |
IllegalStateException: "Error guardando archivo en disco" | I/O error during write | Check disk space and permissions |
Best Practices
- Always use relative paths when persisting to database
- Normalize paths using service methods, not manual string operations
- Validate file types before calling
storePersonFile() - Verify SHA-256 hashes when serving sensitive documents
- Use
loadAsResource()instead of direct file access for HTTP responses
See Also
- Blockchain Services - Document synchronization to Fabric
- Security Configuration - Access control for file operations
