FileSharer Development Notes 1 — The Small Server Behind a Shared File

한국어로 읽기

FileSharer Development Notes · 01 / 10

Three developers explain selecting a file and passing it along through a share link.
AI illustration · Three developers explain selecting a file and passing it along through a share link.

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.

The original Korean-language page generated by BuildDownloadHtml with a sample folder. All names and contents are examples, not real users’ sharing records or transfer results.
The original Korean-language page generated by BuildDownloadHtml with a sample folder. All names and contents are examples, not real users’ sharing records or transfer results.

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.

Source references
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.

댓글