Backend em Spring Boot para um “mini NAS” doméstico: faz upload de arquivos grandes em partes (chunks), salva o arquivo no disco e guarda metadados no banco via JPA. Também oferece listagem paginada e download por streaming (sem alocar o arquivo inteiro na RAM).
- Upload em 3 etapas:
POST /upload/init→ cria uma “sessão” e retorna umuploadIdgerado aleatoriamentePOST /upload/chunk→ envia um pedaço do arquivo (multipart)POST /upload/finish→ junta os.partNe persiste metadados no banco
- Download de arquivo por streaming:
GET /files/{id}/content→StreamingResponseBodycomInputStream.transferTo(...)
- Listagem de arquivos com paginação:
GET /files→ retornaPage<FileDTO>
- Organização em camadas (Controller / Service / Repository) e DTO para listagem
- Java + Spring Boot (Spring Web / Spring Data JPA)
- Persistência: JPA (configure o banco no
application.properties) - Armazenamento de arquivos: filesystem local (pasta
Files/uploadsno diretório do projeto)
O banco guarda somente informações como id, nome, tamanho, data, path e temporary path.
O conteúdo do arquivo fica no disco.
A aplicação cria/usa (a partir do user.dir do projeto):
Files/uploads/<nomeSemExtensao>/<arquivo>→ arquivo finalFiles/tempUploads/<uploadId>/<uploadId>.partN→ chunks temporários
Obs.: O merge usa um buffer (atualmente) de
50MB(verUuidEntity.fileChunkSize).
- Configure o banco (JPA) no
application.properties(exemplos abaixo). - Suba a aplicação pelo seu build (Maven ou Gradle).
./mvnw spring-boot:run
# ou
mvn spring-boot:runA aplicação expõe páginas simples:
GET /→ redireciona/abre a tela de uploadGET /upload→ tela de uploadGET /download→ tela de download
Ajuste conforme seu banco. O projeto usa
JpaRepository(FileResource).
spring.datasource.url=jdbc:h2:file:./data/springnas
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
spring.h2.console.enabled=truespring.datasource.url=jdbc:mysql://localhost:3306/springnas
spring.datasource.username=root
spring.datasource.password=senha
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialectCria a sessão e retorna um uploadId.
Request
POST /upload/initContent-Type: application/json
Body:
{
"fileName": "video.mp4",
"fileSize": 123456789
}Response
{ "uploadId": "Ab3kP9xQ1" }Envia um chunk do arquivo (multipart).
POST /upload/chunkmultipart/form-data
Campos:
uploadId(string)chunkNumber(número; recomendado começar em 1)file(o blob do chunk)
Junta os .partN, grava o arquivo final e salva metadados no banco.
Request
POST /upload/finishContent-Type: application/json
Body:
{ "uploadId": "Ab3kP9xQ1" }Response
200 OK
GET /files
Exemplo:
/files?page=0&size=10&sort=id,desc
Response: Page<FileDTO> (campos: id, name, size, date)
GET /files/{id}/content
Retorna:
Content-Type: application/octet-streamContent-Length: <tamanho>Content-Disposition: inline; filename="..."
- Sessão de upload é em memória (se reiniciar a aplicação, perde o estado do
uploadId) - Não há resume/retry inteligente nem checksum (integridade) dos chunks
- Não há suporte a HTTP Range no download (sem resume parcial)
- Tratamento de erros HTTP (404/400) pode ser melhorado (MVP)
