Skip to main content

Design a File Storage System like Google Drive/ DropBox

Problem Statement

Design a file storage system like Google Drive that allows users to upload files, organize them into folders, and optionally share them with other users. The system should support basic file operations like upload, download, delete, and sharing with controlled access.


Functional Requirements

  • Users should be able to upload files into the system
  • Files can be organized inside folders
  • Users should be able to create folders inside folders
  • Files can be downloaded by authorized users
  • Files and folders can be shared with other users
  • Access control should be supported (READ, WRITE)
  • Users should be able to delete files and folders

Objects Required

  • User
  • Drive
  • FileSystemItem
  • File
  • Folder
  • Permission
  • PermissionType

PermissionType Enum


public enum PermissionType {
    READ,
    WRITE
}

The PermissionType enum defines access levels in the system. READ allows viewing/downloading, while WRITE allows modifying or deleting content.


FileSystemItem (Abstract Class)


import java.util.*;

public abstract class FileSystemItem {

    protected String id;
    protected String name;
    protected Folder parent;

    public FileSystemItem(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public abstract void delete();
}

The FileSystemItem class is the base for both files and folders. It captures common properties like id and name.

The constructor ensures every item has identity when created.

The getName() method is used when listing files and folders in the UI or during search operations.

The delete() method is abstract because deletion behaves differently for files and folders.


File Class


public class File extends FileSystemItem {

    private String content;
    private long size;

    public File(String id, String name, String content) {
        super(id, name);
        this.content = content;
        this.size = content.length();
    }

    public String getContent() {
        return content;
    }

    public long getSize() {
        return size;
    }

    @Override
    public void delete() {
        this.content = null;
        this.size = 0;
    }
}

The File class represents an actual stored file in the system.

The constructor initializes file content and automatically calculates its size.

The getContent() method is used when a user downloads or previews a file.

The getSize() method helps in storage tracking and quota management.

The delete() method clears file data, simulating removal from storage.


Folder Class


import java.util.*;

public class Folder extends FileSystemItem {

    private List children;

    public Folder(String id, String name) {
        super(id, name);
        this.children = new ArrayList<>();
    }

    public void addItem(FileSystemItem item) {
        children.add(item);
    }

    public void removeItem(FileSystemItem item) {
        children.remove(item);
    }

    public List listItems() {
        return children;
    }

    @Override
    public void delete() {
        for (FileSystemItem item : children) {
            item.delete();
        }
        children.clear();
    }
}

The Folder class represents a directory that can contain files and other folders.

The constructor initializes an empty folder structure.

The addItem() method adds files or subfolders into the current folder.

The removeItem() method removes an item from the folder without affecting other contents.

The listItems() method returns everything inside the folder, similar to how a file explorer works.

The delete() method recursively deletes everything inside the folder before clearing it. This ensures no orphaned files remain in the system.


User Class


public class User {

    private String userId;
    private String name;

    public User(String userId, String name) {
        this.userId = userId;
        this.name = name;
    }

    public String getUserId() {
        return userId;
    }
}

The User class represents a system user who owns files and folders or accesses shared content.


Permission Class


import java.util.*;

public class Permission {

    private User user;
    private PermissionType type;

    public Permission(User user, PermissionType type) {
        this.user = user;
        this.type = type;
    }

    public User getUser() {
        return user;
    }

    public PermissionType getType() {
        return type;
    }
}

The Permission class defines what access a user has on a file or folder.

The constructor binds a user with a specific permission type.

The getUser() method is used when validating access control during file operations.

The getType() method determines whether the user can only read or also modify content.


Drive Class


import java.util.*;

public class Drive {

    private Folder root;
    private Map> permissions;

    public Drive(Folder root) {
        this.root = root;
        this.permissions = new HashMap<>();
    }

    public void share(String itemId, Permission permission) {

        permissions
            .computeIfAbsent(itemId, k -> new ArrayList<>())
            .add(permission);
    }

    public boolean hasAccess(String itemId, User user, PermissionType type) {

        if (!permissions.containsKey(itemId)) return false;

        for (Permission p : permissions.get(itemId)) {
            if (p.getUser().getUserId().equals(user.getUserId())
                    && p.getType() == type) {
                return true;
            }
        }
        return false;
    }

    public Folder getRoot() {
        return root;
    }
}

The Drive class is the main entry point of the system, similar to Google Drive.

The constructor initializes the root folder and permission storage.

The share() method assigns access permissions to a file or folder for a specific user.

The hasAccess() method checks whether a user has the required permission before performing operations like download or delete.

The getRoot() method provides access to the root directory for traversal operations.


Main Class


import java.util.*;

public class Main {

    public static void main(String[] args) {

        User u1 = new User("U1", "A");
        User u2 = new User("U2", "B");

        Folder root = new Folder("F0", "root");
        Folder docs = new Folder("F1", "docs");

        File file1 = new File("FI1", "notes.txt", "Hello World");

        root.addItem(docs);
        docs.addItem(file1);

        Drive drive = new Drive(root);

        drive.share("FI1", new Permission(u2, PermissionType.READ));

        System.out.println(
                drive.hasAccess("FI1", u2, PermissionType.READ)
        );
    }
}

The main method simulates a simple file system flow.

We create users, folders, and files, then build a hierarchy similar to a real drive system.

Finally, we share a file and verify whether another user has access to it.


Class Diagram

UseruserId : Stringname : StringFileSystemItemid : Stringname : Stringparent : Folderdelete() : voidFilecontent : Stringsize : longFolderchildren : List<FileSystemItem>addItem(item : FileSystemItem) : voidremoveItem(item : FileSystemItem) : voidlistItems() : List<FileSystemItem>Permissionuser : Usertype : PermissionTypePermissionTypeREADWRITEDriveroot : Folderpermissions : Map<String, List<Permission>>share(itemId : String, permission : Permission) : voidhasAccess(itemId : String, user : User, type : PermissionType) : booleangetRoot() : FolderMainmain(args : String[]) : void

Also See

Comments

Popular posts from this blog

Designing a Parking Lot - Low Level Design

Problem Statement Design a parking lot that can handle vehicles entering and leaving while managing parking across multiple floors. Each vehicle should be assigned a suitable parking spot based on its type, and the spot should be freed once the vehicle exits. The design should also support generating a ticket at entry and optionally calculating the parking fee based on the duration of stay. Asked In Companies Amazon Google Microsoft Uber Walmart Flipkart Meta PayPal Oracle Salesforce Adobe Apple Intuit LinkedIn Atlassian Functional Requirements The design should support multiple vehicle types such as bikes, cars, and trucks A vehicle must be assigned a parking spot compatible with its type A parking spot cannot be assigned to more than one vehicle at a time The parking lot should support multiple levels (floors) The design should search and allocate an availa...

Most Frequently Asked Low Level Design(LLD) Interview Questions

Below are the curated list of most commonly asked Low Level Design (LLD) interview problems. Each problem includes a short description and a link to the complete solution with code and class diagrams. Design Parking Lot System The system should handle parking for different vehicle types such as bikes, cars, and trucks. It should manage slot allocation, availability tracking, and entry/exit flow. The design also ensures efficient usage of parking space under varying load conditions. View Solution Design Elevator / Lift System The system should support multiple elevators operating across floors with request handling logic. It focuses on scheduling algorithms to minimize wait time and optimize movement. It also manages direction control and concurrent floor requests. View Solution Design Movie Ticket Booking System The system should allow users to browse movies, select shows, and book seats. It handles seat ...

Software Design Patterns for LLD Interviews: A Complete Guide

Software Design Patterns for LLD Interviews: A Complete Guide In Software Development Engineer (SDE) interviews—especially for mid-level and senior roles—low-level design (LLD) rounds assess your ability to write clean, reusable, maintainable, and extensible code. The foundation of resolving these architectural challenges lies in the standard Gang of Four (GoF) Design Patterns. Rather than memorizing theoretical definitions, interviewers expect you to apply these patterns to real-world scenarios, identifying the trade-offs of each. Below is a comprehensive guide to the 12 most frequently asked design patterns in LLD interviews, categorized by their classification (Creational, Structural, and Behavioral). Each pattern contains a concrete, real-world Java implementation and a detailed breakdown of design decisions. Creational Design Patterns Creational design patterns deal with object creation mechanisms. They abstract the instantiation process, making a system independent of how...