Saturday, May 15, 2021

Upload-Download Any FileType .PDF,MP3,MP4,.DOCX in Database and Without Database in SpringBoot Gradle Build System - Java

 Upload-Download Any FileType .PDF,MP3,MP4,.DOCX in Database and Without Database in SpringBoot :

I have asked to create a file upload-download demo in spring boot on the Gradle build system. So this for my students and beginners who want to understand the API how to develop file upload-download. Even you can view the same in your browser.

Our Spring Boot Application will provide APIs for:

Uploading File to MySQL database

downloading File database with the link

These are APIs to be exported:

Methods Urls Actions

POST /upload upload a File

GET /files get List of Files (name, url, type, size)

GET /files/[fileId] download a File

The uploaded files will be stored in the MySQL Database files table with these fields: id, name, type, and data as BLOB type (Binary Large Object is for storing binary data like file, image, audio, or video).

Let me explain it briefly.

– FileDocument is the data model corresponding to the files table in the database.

– FileDBRepository extends the Spring Data JPA repository which has methods to store and retrieve files.

– FilesStorageService uses FileDBRepository to provide methods for saving new file, get file by id, get list of Files.

– FilesController uses FilesStorageService to export Rest APIs: POST a file, GET all files’ information, download a File.

– FileUploadExceptionAdvice handles exceptions when the controller processes file upload.

– ResponseFile contains information of the file (name, URL, type, size) for HTTP response payload.

– application.YAML contains configuration for Servlet Multipart and MySQL database connection.

– pom.xml for Spring Boot, Spring Data JPA, and MySQL connector dependency.

Full Souce Code Accessible Here on below path:
https://github.com/Abhinaw/demo/tree/master

Below is the test results for reference :



Folder Location where file is getting stored : FileStorage Folder in project

     Folder Location where file is getting stored

Source Code :

import com.greenlearner.fileuploaddownload.dto.FileUploadResponse;
import com.greenlearner.fileuploaddownload.service.FileStorageService;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@RestController
public class UploadDownloadWithFileSystemController {

private FileStorageService fileStorageService;

public UploadDownloadWithFileSystemController(FileStorageService fileStorageService) {
this.fileStorageService = fileStorageService;
}

@PostMapping("single/upload")
FileUploadResponse singleFileUplaod(@RequestParam("file") MultipartFile file) {

String fileName = fileStorageService.storeFile(file);

///http://localhost:8081/download/abc.jpg
String url = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/download/")
.path(fileName)
.toUriString();

String contentType = file.getContentType();

FileUploadResponse response = new FileUploadResponse(fileName, contentType, url);

return response;

}

@GetMapping("/download/{fileName}")
ResponseEntity<Resource> downLoadSingleFile(@PathVariable String fileName, HttpServletRequest request) {

Resource resource = fileStorageService.downloadFile(fileName);

// MediaType contentType = MediaType.APPLICATION_PDF;

String mimeType;

try {
mimeType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException e) {
mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
}
mimeType = mimeType == null ? MediaType.APPLICATION_OCTET_STREAM_VALUE : mimeType;

return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(mimeType))
// .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;fileName="+resource.getFilename())
.header(HttpHeaders.CONTENT_DISPOSITION, "inline;fileName=" + resource.getFilename())
.body(resource);
}

@PostMapping("/multiple/upload")
List<FileUploadResponse> multipleUpload(@RequestParam("files") MultipartFile[] files) {

if (files.length > 7) {
throw new RuntimeException("too many files");
}
List<FileUploadResponse> uploadResponseList = new ArrayList<>();
Arrays.asList(files)
.stream()
.forEach(file -> {
String fileName = fileStorageService.storeFile(file);

///http://localhost:8081/download/abc.jpg
String url = ServletUriComponentsBuilder.fromCurrentContextPath()
.path("/download/")
.path(fileName)
.toUriString();

String contentType = file.getContentType();

FileUploadResponse response = new FileUploadResponse(fileName, contentType, url);
uploadResponseList.add(response);
});

return uploadResponseList;
}

@GetMapping("zipDownload")
void zipDownload(@RequestParam("fileName") String[] files, HttpServletResponse response) throws IOException {
//zipoutstream - zipentry+zipentry

try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
Arrays.asList(files)
.stream()
.forEach(file -> {
Resource resource = fileStorageService.downloadFile(file);

ZipEntry zipEntry = new ZipEntry(resource.getFilename());

try {
zipEntry.setSize(resource.contentLength());
zos.putNextEntry(zipEntry);

StreamUtils.copy(resource.getInputStream(), zos);

zos.closeEntry();
} catch (IOException e) {
System.out.println("some exception while ziping");
}
});
zos.finish();

}

response.setStatus(200);
response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;fileName=zipfile");
}
}

This is without a database just upload and download files to a particular location.

application.yaml:

server:
port: 8081

file:
storage:
location: fileStorage

spring:
servlet:
multipart:
enabled: true
location: temp123
file-size-threshold: 5MB
max-file-size: 20MB
max-request-size: 20MB

datasource:
url: jdbc:mysql://localhost:3306/db?useSSL=false
username: root
password:
driver-class-name: com.mysql.cj.jdbc.Driver



Gradle dependency:

dependencies {
//my sql connector
compile 'mysql:mysql-connector-java:8.0.17'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}

Thanks.


1 comment:

Anonymous said...

Very good example.