91. Design File Downloader Library

Design File Downloader Library
Design and implement a File Downloader Library.

The library should support downloading text files. It should expose controls to pause, resume, restart, and cancel downloads.

Download State Model

States: RUNNING, PAUSED, COMPLETED, FAILED, CANCELED.

  • COMPLETED, FAILED, and CANCELED are terminal states.
  • RUNNING and PAUSED are active states.
  • When a download reaches a terminal state, it becomes inactive.

Methods

Constructor

FileDownloaderLibrary(int totalMemory, int maxConcurrentDownloads)
  • maxConcurrentDownloads >= 1.
    It is the maximum number of active downloads allowed at the same time.
  • RUNNING and PAUSED downloads are active.
  • COMPLETED, FAILED, and CANCELED downloads are inactive.
  • totalMemory is the maximum sum of characters currently stored in memory across all active downloads.
  • When a download becomes inactive, its buffered characters are flushed to disk and removed from memory.

Create Download Request

boolean createDownload(String downloadId, int chunksCount, int fileSize)
  • Creates a new download with the given id. This method is always called with a non-blank and globally unique downloadId.
  • Each file is downloaded as chunksCount chunks in parallel.
  • Chunk ids are numbered from 0 to chunksCount - 1.
  • fileSize is the total number of characters expected in the final file.
  • A newly created download starts in RUNNING state with 0 downloaded characters.
  • returns true if download is successfully created else returns false if downloadId already exists or if number of active downloads is already maxConcurrentDownloads

Download Text

String downloadText(String downloadId, int chunkId, String text)
  • Appends text to the specified chunk of the given download.
  • The library tracks cumulative text length across all chunks of the same downloadId.
  • Returns DOWNLOAD_NOT_FOUND, INVALID_CHUNK_ID as appropriate.
  • if state is PAUSED, return error DOWNLOAD_PAUSED, and do not append text
  • If the total downloaded characters become exactly equal to fileSize, the download immediately becomes COMPLETED.
  • If accepting the new text would make total downloaded characters exceed fileSize, the download becomes FAILED with error FILE_TOO_LARGE.
  • If accepting the new text would exceed the library memory budget across all active downloads, the call returns a summary with error NO_MEMORY and the new text is not appended.
  • If the download is already in a terminal state, the method returns a summary with error INACTIVE_DOWNLOAD.
  • The return value is a stringified summary such as "state=RUNNING,progress=50,error=".
  • progress is always % of charactes transferred turncated to int. e.g. total 6/11 characters are transferred = 54%

Pause Download

boolean pauseDownload(String downloadId)
  • Valid only when the download is in RUNNING state.
  • Returns true if paused successfully, otherwise returns false.

Resume Download

boolean resumeDownload(String downloadId)
  • Valid only when the download is in PAUSED state.
  • Returns true if resumed successfully, otherwise returns false.

Cancel Download

boolean cancelDownload(String downloadId)
  • Valid for active downloads.
  • The download moves to CANCELED state.
  • Returns true if canceled successfully, otherwise returns false if downloadId doesn't exists or download is already inactive.

Get Download Status

String getDownloadStatus(String downloadId)
  • Returns a stringified status object.
  • Example format: "state=RUNNING,progress=42,error=,downloadedChars=42,totalChars=100"
  • For unknown downloadId, return: "state=NOT_FOUND,progress=0,error=DOWNLOAD_NOT_FOUND,downloadedChars=0,totalChars=0"

Examples

Example Block 1: Successful Download, Invalid Chunk, and Inactive Download Error

  • FileDownloaderLibrary(totalMemory=20, maxConcurrentDownloads=2)library initialized
  • createDownload(downloadId="DL-1", chunksCount=2, fileSize=10)true
  • getDownloadStatus(downloadId="DL-1")"state=RUNNING,progress=0,error=,downloadedChars=0,totalChars=10"
  • downloadText(downloadId="DL-1", chunkId=2, text="x")"state=RUNNING,progress=0,error=INVALID_CHUNK_ID"
  • downloadText(downloadId="DL-1", chunkId=0, text="hello")"state=RUNNING,progress=50,error="
  • downloadText(downloadId="DL-1", chunkId=1, text="world")"state=COMPLETED,progress=100,error="
  • getDownloadStatus(downloadId="DL-1")"state=COMPLETED,progress=100,error=,downloadedChars=10,totalChars=10"
  • downloadText(downloadId="DL-1", chunkId=0, text="!")"state=COMPLETED,progress=100,error=INACTIVE_DOWNLOAD"
  • cancelDownload(downloadId="DL-1")false

Example Block 2: Pause, Resume, Cancel, and Unknown Download

  • FileDownloaderLibrary(totalMemory=30, maxConcurrentDownloads=2)library initialized
  • createDownload(downloadId="DL-2", chunksCount=3, fileSize=12)true
  • downloadText(downloadId="DL-2", chunkId=0, text="abcd")"state=RUNNING,progress=33,error="
  • pauseDownload(downloadId="DL-2")true
  • downloadText(downloadId="DL-2", chunkId=1, text="ef")"state=PAUSED,progress=33,error=DOWNLOAD_PAUSED"
  • getDownloadStatus(downloadId="DL-2")"state=PAUSED,progress=33,error=,downloadedChars=4,totalChars=12"
  • resumeDownload(downloadId="DL-2")true
  • downloadText(downloadId="DL-2", chunkId=1, text="efgh")"state=RUNNING,progress=66,error="
  • cancelDownload(downloadId="DL-2")true
  • getDownloadStatus(downloadId="DL-2")"state=CANCELED,progress=66,error=,downloadedChars=8,totalChars=12"
  • resumeDownload(downloadId="DL-2")false
  • getDownloadStatus(downloadId="UNKNOWN")"state=NOT_FOUND,progress=0,error=DOWNLOAD_NOT_FOUND,downloadedChars=0,totalChars=0"

Example Block 3: FILE_TOO_LARGE, NO_MEMORY, and Active Download Limit

  • FileDownloaderLibrary(totalMemory=10, maxConcurrentDownloads=2)library initialized
  • createDownload(downloadId="DL-3", chunksCount=2, fileSize=5)true
  • createDownload(downloadId="DL-4", chunksCount=1, fileSize=6)true
  • createDownload(downloadId="DL-5", chunksCount=1, fileSize=7)false
  • downloadText(downloadId="DL-3", chunkId=0, text="abc")"state=RUNNING,progress=60,error="
  • downloadText(downloadId="DL-4", chunkId=0, text="wxyz")"state=RUNNING,progress=66,error="
  • downloadText(downloadId="DL-3", chunkId=1, text="def")"state=FAILED,progress=60,error=FILE_TOO_LARGE"
  • getDownloadStatus(downloadId="DL-3")"state=FAILED,progress=60,error=FILE_TOO_LARGE,downloadedChars=3,totalChars=5"
  • createDownload(downloadId="DL-5", chunksCount=1, fileSize=7)true
  • downloadText(downloadId="DL-5", chunkId=0, text="1234567")"state=RUNNING,progress=0,error=NO_MEMORY"
  • cancelDownload(downloadId="DL-4")true
  • downloadText(downloadId="DL-5", chunkId=0, text="1234567")"state=COMPLETED,progress=100,error="
  • getDownloadStatus(downloadId="DL-5")"state=COMPLETED,progress=100,error=,downloadedChars=7,totalChars=7"




Please use Laptop/Desktop or any other large screen to add/edit code.