Skip to content

Fix(assets): attached files land in assets/, and uploads are no longer corrupted - #15

Open
adibhanna wants to merge 1 commit into
mainfrom
fix/attached-files-assets-and-upload-encoding
Open

Fix(assets): attached files land in assets/, and uploads are no longer corrupted#15
adibhanna wants to merge 1 commit into
mainfrom
fix/attached-files-assets-and-upload-encoding

Conversation

@adibhanna

Copy link
Copy Markdown
Contributor

Both bugs were reported against the Android app, which carries the same bridge code. This app had them identically, so it gets the same fix. Android side: ZenNotes/zennotesandroid#41.

Local vault: the file went to the vault root

importDroppedFile asked for a unique name in '', the vault root, wrote the file there, and hand-built the link as '../'.repeat(depth) + filename, so a note in a folder got ![name](<../name.jpg>). Paste already wrote to assets/, and so did the cloud vault.

Desktop had this exact bug and fixed it in ZenNotes#377; the port here was missed.

Now: assets/, linked by vault-relative path, an image as ![[assets/pic.jpg]].

Self-hosted vault: every upload arrived corrupt

The upload hand-built its multipart body as one string and marked the file part Content-Transfer-Encoding: base64. RFC 7578 dropped that header from multipart/form-data and Go's mime/multipart ignores it, so the server wrote the base64 text to disk as the file's bytes: right name, about a third larger, unreadable by anything.

The bytes must stay base64 to cross the native bridge, since a CapacitorHttp string body is written out as UTF-8 and mangles anything above 0x7F. dataType: 'formData' is the supported route: CapacitorUrlRequest.getRequestDataFromFormData decodes a base64File entry and writes the raw bytes into the part, exactly matching the Android layer. The sibling direct-object upload already used the same mechanism with dataType: 'file'.

Proven against the real Go server

body stored begins matches original
old 638,352 bytes iVBORw0K (base64 text) no
new 478,762 bytes \x89PNG yes, identical sha256

Notes

…r corrupted

Both bugs were reported against the Android app, which carries the same
bridge code; this app had them identically, so it gets the same fix.

On a LOCAL vault, attaching a file wrote it to the vault ROOT, next to the
notes, and linked it with a hand-built `'../'.repeat(depth)` path, so a
note in a folder got `![name](<../name.jpg>)`. Paste already wrote to
`assets/`, and so did the cloud vault. Desktop had the same bug and fixed
it in ZenNotes#377; the port here was missed. Attach now writes to
`assets/` and links by vault-relative path, an image as
`![[assets/pic.jpg]]`, matching paste and the cloud vault.

On a SELF-HOSTED vault, every uploaded attachment arrived corrupt. The
upload hand-built its multipart body as one string and marked the file
part `Content-Transfer-Encoding: base64`. That header is a MIME construct:
RFC 7578 dropped it from multipart/form-data and Go's mime/multipart
ignores it, so the server wrote the base64 TEXT to disk as the file's
bytes, a third larger than the original and unreadable by anything.

The bytes must stay base64 to cross the native bridge at all, since a
CapacitorHttp string body is written out as UTF-8 and mangles anything
above 0x7F. `dataType: 'formData'` is the supported way through:
CapacitorUrlRequest.getRequestDataFromFormData decodes a `base64File`
entry and writes the raw bytes into the part, matching Android. The
sibling direct-object upload already used the same mechanism with
`dataType: 'file'`.

Verified against the real Go server by posting both body shapes: the old
one stored 638352 bytes beginning `iVBORw0K`, the base64 text of the PNG,
and the new one stored 478762 bytes with the same sha256 as the original.

Claude-Session: https://claude.ai/code/session_01AYTRixg5TJmxn2j6FCqfUD
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant