FileSharer Development Notes 6 — Checking QR Code Limits in Bytes, Not Characters
FileSharer Development Notes · 06 / 10

Adding a QR image next to a sharing link makes it easier to open the address on a phone. The appearance of an image alone does not establish success, though. We also need to check whether the string decoded by the camera matches the original link, and whether Korean text or long addresses take a different processing path.

FileSharer's QrCodeHelper first attempts to generate a QR code locally. For this investigation, I ran only its offline generation function in isolation to check the boundary values. No real sharing addresses or decryption keys were sent to an external service.
A narrower scope keeps the implementation simpler
This implementation uses a subset of combinations from QR versions 1 through 5. It selects error correction level M for versions 1–3 and level L for versions 4–5, limiting support to combinations that use one Reed–Solomon block. In byte mode, the maximum input accepted by this code is 106 bytes.
Here, 106 is not the maximum capacity of all QR codes. It is the limit of the combinations implemented in this project. This needs to be distinguished from QR generators that support larger versions or other data modes.
The code scores eight mask candidates using penalties, selects a mask, and adds a margin around the image. The requirement for a four-module margin around a QR code is also described in DENSO WAVE's QR code placement guide. Cropping that margin for visual design changes the conditions under which the code can be recognized.
Equal character counts do not mean equal byte counts
The offline function converts the string to UTF-8 bytes for processing. An uppercase ASCII A and a Korean character do not take up the same number of bytes. These are the four inputs passed to the actual function:
| Input | UTF-8 length | Original function result |
|---|---|---|
| Demo local sharing address | 32 bytes | Image generated |
| A repeated 106 times | 106 bytes | Image generated |
| A repeated 107 times | 107 bytes | null |
| 파일 공유 데모 (Korean for “file sharing demo”) | 20 bytes | Image generated |
The three generated images were passed to the OpenCV QR decoder, and each decoded string was confirmed to match its original input. The check therefore went beyond whether an image file had been created. Success in these three cases cannot be generalized to every character combination, printed size, or camera environment.
Read what happens after null, too
The higher-level Generate function returns immediately when offline generation succeeds. If it fails or returns null, processing moves to a fallback that calls an online QR API. A comment describes this as a path for long URLs, but the code can also take the same fallback if offline generation throws an exception.
This distinction matters when a sharing link contains a secret. If an external download link carries decryption information after its #, encoding the entire string into the QR API's data parameter sends that input string to the service. Normal browser handling of a fragment and passing a string to a QR generation API are different operations.
“Offline first” therefore should not be presented as meaning “never sends data externally.” The online fallback was not called during this investigation.
When explaining the failure may be the better choice
For a tool that shares personal files, explaining the length limit and offering a Copy Link button may be more appropriate than sending the link externally when QR generation fails. Another option is to replace the implementation with a validated local encoder that supports a sufficient range of inputs. These are proposed improvements, not current features.
Test inputs should also cover more than filling up the length limit. ASCII boundaries, Korean text, addresses expanded by URL encoding, the actual sharing-link format, and the result displayed on a small screen should be checked separately. In particular, when testing links with keys or PINs, use examples that are safe to disclose instead of real values.
What makes a QR image complete
The findings for this project are clear. Three selected inputs were generated locally and successfully decoded back to their originals, while a 107-byte ASCII input exceeded this function's supported range. What users need, more than the details of a complex QR implementation, is behavior that clearly communicates whether generation succeeded, whether the content matches, and where the input was sent.
FileSharer.cs:279–321 QrCodeHelper.Generate · FileSharer.cs:404–568 GenerateStandardOfflineQR · FileSharer.cs:614–736 Masking and penalty calculation
Proposed improvements are distinguished from implemented behavior.
댓글
댓글 쓰기