FileSharer Development Notes 6 — Checking QR Code Limits in Bytes, Not Characters

FileSharer Development Notes · 06 / 10

한국어 버전

Three developers explain QR payload capacity and clear margins. The mosaic is a conceptual illustration.
AI illustration · Three developers explain QR payload capacity and clear margins. The mosaic is a conceptual illustration.

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.

Demo QR codes created by the original offline generation function, alongside their decoding results. The QR codes contain example addresses, not connection-test targets; no online QR service was called.
Demo QR codes created by the original offline generation function, alongside their decoding results. The QR codes contain example addresses, not connection-test targets; no online QR service was called.

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.

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

댓글