Java Cloud File Storage Service

Loading

Building a Java Cloud File Storage Service involves creating a system that allows users to upload, store, and manage files in the cloud. Below is a step-by-step guide to building such a service, including the key components, design considerations, and example code snippets.


1. Requirements Analysis

Before starting, define the requirements for the service:

  • User Roles: Admin (manage users) and User (upload and manage files).
  • File Upload: Allow users to upload files to the cloud.
  • File Storage: Store files securely in the cloud.
  • File Management: Allow users to view, download, and delete files.
  • Security: Secure access to the service for authenticated users.

2. System Design

Modules

  1. User Management
  • Register and authenticate users.
  1. File Upload
  • Allow users to upload files to the cloud.
  1. File Storage
  • Store files securely in the cloud.
  1. File Management
  • Allow users to view, download, and delete files.
  1. Security
  • Secure access to the service for authenticated users.

Database Design

  • User Table: user_id, username, password, role
  • File Table: file_id, user_id, name, size, upload_date, file_path

3. Technology Stack

  • Backend: Java (Spring Boot)
  • Frontend: Thymeleaf (for simplicity) or Angular/React (for advanced UI)
  • Database: MySQL or H2 (for testing)
  • Build Tool: Maven or Gradle
  • Security: Spring Security for authentication and authorization
  • Cloud Storage: AWS S3, Google Cloud Storage, or local file system

4. Implementation

Step 1: Set Up the Project

Create a Spring Boot project using Spring Initializr with the following dependencies:

  • Spring Web
  • Spring Data JPA
  • Spring Security
  • Thymeleaf (for UI)
  • MySQL Driver (or H2 for testing)
  • AWS SDK (if using AWS S3) or Google Cloud Storage Client (if using Google Cloud Storage)

Step 2: Define Entities

Create Java classes for the database tables.

User.java

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userId;
    private String username;
    private String password;
    private String role; // "ADMIN" or "USER"

    // Getters and Setters
}

File.java

@Entity
public class File {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long fileId;
    private Long userId;
    private String name;
    private long size;
    private LocalDateTime uploadDate;
    private String filePath;

    // Getters and Setters
}

Step 3: Create Repositories

Use Spring Data JPA to create repositories for database operations.

UserRepository.java

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username); // For authentication
}

FileRepository.java

public interface FileRepository extends JpaRepository<File, Long> {
    List<File> findByUserId(Long userId); // For user's file list
}

Step 4: Implement Services

Create service classes to handle business logic.

UserService.java

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public void registerUser(User user) {
        userRepository.save(user);
    }

    public boolean authenticateUser(String username, String password) {
        Optional<User> user = userRepository.findByUsername(username);
        return user.isPresent() && user.get().getPassword().equals(password);
    }
}

FileService.java

@Service
public class FileService {
    @Autowired
    private FileRepository fileRepository;

    @Value("${file.upload-dir}")
    private String uploadDir;

    public void uploadFile(MultipartFile file, Long userId) throws IOException {
        String fileName = file.getOriginalFilename();
        String filePath = uploadDir + "/" + fileName;
        Files.copy(file.getInputStream(), Paths.get(filePath), StandardCopyOption.REPLACE_EXISTING);

        File fileEntity = new File();
        fileEntity.setUserId(userId);
        fileEntity.setName(fileName);
        fileEntity.setSize(file.getSize());
        fileEntity.setUploadDate(LocalDateTime.now());
        fileEntity.setFilePath(filePath);
        fileRepository.save(fileEntity);
    }

    public List<File> getUserFiles(Long userId) {
        return fileRepository.findByUserId(userId);
    }

    public Resource downloadFile(Long fileId) throws FileNotFoundException {
        File file = fileRepository.findById(fileId).orElseThrow();
        Path path = Paths.get(file.getFilePath());
        Resource resource = new UrlResource(path.toUri());
        if (resource.exists() || resource.isReadable()) {
            return resource;
        } else {
            throw new FileNotFoundException("File not found: " + file.getFilePath());
        }
    }

    public void deleteFile(Long fileId) throws IOException {
        File file = fileRepository.findById(fileId).orElseThrow();
        Files.deleteIfExists(Paths.get(file.getFilePath()));
        fileRepository.deleteById(fileId);
    }
}

Step 5: Create Controllers

Create controllers to handle HTTP requests.

UserController.java

@RestController
@RequestMapping("/users")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/register")
    public void registerUser(@RequestBody User user) {
        userService.registerUser(user);
    }

    @PostMapping("/authenticate")
    public boolean authenticateUser(@RequestParam String username, @RequestParam String password) {
        return userService.authenticateUser(username, password);
    }
}

FileController.java

@RestController
@RequestMapping("/files")
public class FileController {
    @Autowired
    private FileService fileService;

    @PostMapping("/upload")
    public void uploadFile(@RequestParam("file") MultipartFile file, @RequestParam Long userId) throws IOException {
        fileService.uploadFile(file, userId);
    }

    @GetMapping("/{userId}")
    public List<File> getUserFiles(@PathVariable Long userId) {
        return fileService.getUserFiles(userId);
    }

    @GetMapping("/download/{fileId}")
    public ResponseEntity<Resource> downloadFile(@PathVariable Long fileId) throws IOException {
        Resource resource = fileService.downloadFile(fileId);
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                .body(resource);
    }

    @DeleteMapping("/{fileId}")
    public void deleteFile(@PathVariable Long fileId) throws IOException {
        fileService.deleteFile(fileId);
    }
}

Step 6: Implement Security

Use Spring Security to secure the application.

SecurityConfig.java

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserRepository userRepository;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(username -> userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User not found")));
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .antMatchers("/users/**", "/files/**").authenticated()
            .anyRequest().permitAll()
            .and()
            .httpBasic();
    }
}

Step 7: Frontend (Optional)

Use Thymeleaf or a frontend framework like Angular/React to create a user interface for the service.


5. Testing

  • Use JUnit and Mockito for unit testing.
  • Test the application using Postman or Swagger for API testing.

6. Deployment

  • Package the application as a JAR/WAR file and deploy it to a server (e.g., Tomcat).
  • Use Docker for containerization and Kubernetes for orchestration (optional).

Example Use Cases

  1. User Registration
  • User registers with details like username and password.
  1. File Upload
  • User uploads a file to the cloud.
  1. File Download
  • User downloads a file from the cloud.
  1. File Management
  • User views and deletes their files.

Leave a Reply

Your email address will not be published. Required fields are marked *