FileSharer Development Notes 1 — The Small Server Behind a Shared File
FileSharer Development Notes · 01 / 10

The shortest explanation of file sharing is “select a file and send a link.” But following that link raises several implementation questions. Can the recipient still download when the source PC is off? How should a folder be delivered? Where does the application reject a request after the owner revokes a share? These are separate problems.

This series starts with the actual C# source of FileSharer, a Windows application. It follows the life of a share, from creation to termination. This first installment focuses on the basic path for sending files within the same network; external tunnels come later.
A share link refers to an item, not a Windows file path
BtnGenerate_Click builds a ShareItem from the selected file or folder. Alongside the source path, the object holds a share ID, creation time, expiration time, download limit, PIN, and revocation flag. The browser receives an address shaped like /d/share-id, rather than the actual Windows path.
That indirection matters because a file and a share have different lifetimes. The owner can revoke a share while keeping the file on disk. Conversely, a stored share can still exist after its source file has moved. “This ID exists” and “this file is available to download now” therefore need separate checks.
The code adds the shared item to an in-memory dictionary and then persists it to disk. This path does not upload the file to a central store. The host reads and sends its local source file when requested, so the source PC and the application need to remain available.
Separate the interface, shared state, and transfer path
Much of the implementation sits in one large C# file, but its responsibilities can still be distinguished.
| Responsibility | Implementation | What it passes on |
|---|---|---|
| File selection and options | MainForm in WinForms | Selected path and access limits |
| Share state | ShareItem and store | The item identified by a share ID |
| Download interface | BuildDownloadHtml | A page for choosing files or a folder download |
| HTTP handling and transfer | TcpListener, ProcessClient, ServeFile | Response headers and file bytes |
| Recovery after a restart | SaveStoreToDisk, LoadStoreFromDisk | Persisted shared items |
These responsibilities do not all need to become separate services at the outset. What matters is knowing which one to inspect when something fails. Seeing the download page establishes that the browser received its HTML. It does not establish that the recipient saved the complete file.
Folder sharing serves two different needs
The actual BuildDownloadHtml method produces both a button for downloading the whole folder as a ZIP and a list of individual files. If a folder contains three documents, someone who needs all of them can choose the ZIP, while someone who needs only one revised document can choose that file.
For this check, a sample-folder contained three newly created text files. The screenshot comes from executing the original HTML-generation method and rendering its output in a browser. It shows the page produced by the code, with its original Korean interface. The check did not start the complete application or establish an external share.
Before inserting a filename into HTML, the code calls HttpUtility.HtmlEncode. A special character in a filename should not change the structure of the page. A value used for display and the same value used inside a download URL belong to different output contexts and need to be handled accordingly.
Treat link creation and reachability as separate steps
A string such as http://host:port/d/id can be assembled even when the network is disconnected. Creating the address therefore does not prove that another PC can reach it. The source has a separate VerifyShareLink path for checking a link after creation.
Checking one boundary at a time makes failures easier to locate: can the host open the page, can another device on the same network reach it, does the source file still exist, and does the received file match the original? The isolated function results in this series should not be read as an end-to-end test of that entire path.
The starting point for reading this project
The organizing concept in FileSharer is the shared item as a state object. Keeping the source path, link identity, and access limits together makes expiration, revocation, and recovery after a restart understandable. The next installment follows that state into download requests, including why “download only once” is more complicated than it initially sounds.
Source snapshot reviewed: 2026-10-01. The screenshot is the result of a local function run with sample data.
FileSharer.cs:20–49 ShareItem · FileSharer.cs:2030–2069 Main · FileSharer.cs:4178–4335 BtnGenerate_Click · FileSharer.cs:4553–4623 StartHttpServer / ListenLoop · FileSharer.cs:5941–6008 BuildDownloadHtml
The original project files were not modified. Proposed improvements are distinguished from implemented behavior.
댓글
댓글 쓰기