shuttlecraft icon indicating copy to clipboard operation
shuttlecraft copied to clipboard

Attachment support

Open ringtailsoftware opened this issue 2 years ago • 14 comments

I've added support for attaching a single file. It was working here (with my other changes), until I merged with the latest composer changes.

Raising a PR in case it's obvious to you what's gone wrong, else I'll continue later...

ringtailsoftware avatar Dec 22 '22 14:12 ringtailsoftware

This is super cool, thank you for this contribution.

One thing I am wondering is if there is a very strong benefit to wrapping the media as base64 in a json file? Does it make it easier to handle in express?

My concerns are that his will result in large files that can't be easily inspected. I would prefer to write them as normal files so that the owner of the instance can look at them without extra tooling. Also, this would allow them to be served out of a static media folder instead of processing them through a handler.

Using the hash of the content to create the filename is nice since it elegantly handles duplicate files.

Also, this will need a way to add the content description as well -- I am happy to work on that if you would prefer?

benbrown avatar Dec 22 '22 16:12 benbrown

In my testing, the POST will fail for files that are larger than about 1 MB. Chrome debugger doesn't really show much - it says the request canceled.

I suspect this has to do with Express hitting the payload size, but I'm not sure. Base64 stuff gets big fast.

benbrown avatar Dec 22 '22 16:12 benbrown

I agree about base64 encoded files getting big. I only chose to do it that way so that each individual media file on disk would have the binary data and the metadata (mimetype, + description, blurhash etc in future). If I just wrote the raw datafile to disk (named by hash), is there already a good place to stash the metadata? Or, should I have a _meta.json file alongside?

ringtailsoftware avatar Dec 22 '22 17:12 ringtailsoftware

I'm happy for you to do the content description, yes. There's some code in cubiti to calculate image file dimensions and the blurhash too, which can be reused: https://github.com/ringtailsoftware/cubiti/blob/main/cubiti-server/routes/mastodon.js#L987

ringtailsoftware avatar Dec 22 '22 17:12 ringtailsoftware

In my testing, the POST will fail for files that are larger than about 1 MB. Chrome debugger doesn't really show much - it says the request canceled.

I suspect this has to do with Express hitting the payload size, but I'm not sure. Base64 stuff gets big fast.

I've just tested ok with an 8MB PNG (Firefox). Took a little while but worked. Initially it was failing due to nginx (https://www.cyberciti.biz/faq/linux-unix-bsd-nginx-413-request-entity-too-large/)

ringtailsoftware avatar Dec 22 '22 20:12 ringtailsoftware

@benbrown I'm done. Ready for you to try it.

ringtailsoftware avatar Dec 22 '22 20:12 ringtailsoftware

you are on fire @ringtailsoftware. I was just looking at your recent commits. I'll try it out when I can!!

benbrown avatar Dec 22 '22 20:12 benbrown

Why do we need to store the metadata separately from where it lives in the post itself?

I think we get mime-type for free if the file gets written out to /media/hash.png

benbrown avatar Dec 22 '22 20:12 benbrown

@ringtailsoftware this is awesome. I might put some work into this while you sleep -- if the power doesn't go out in texas!!

benbrown avatar Dec 22 '22 20:12 benbrown

If we use the file extension then we'd still have to decode ".png" into "image/png" and so on. In theory, so long as the browser sends a valid mimetype this scheme should work for video and other formats without a mapping table.

ringtailsoftware avatar Dec 22 '22 20:12 ringtailsoftware

The original filename must be available in the browser - it could be passed as part of the payload, and then can use that to apply the extension. Ultimately I think it is important to have human readable files in the /media folder (meaning I can look at them with my normal tools)

benbrown avatar Dec 22 '22 20:12 benbrown

The original filename must be available in the browser - it could be passed as part of the payload, and then can use that to apply the extension. Ultimately I think it is important to have human readable files in the /media folder (meaning I can look at them with my normal tools)

Ok, in that case, I'd suggest taking the mimetype "image/png" and renaming the data file to ${hash}.${mimetype.split('/')[1]}. That way the original filename doesn't matter, but you can still view the files easily.

I'm concerned about someone uploading a file called "../../" or a PNG called "foo.jpg", etc.

ringtailsoftware avatar Dec 22 '22 20:12 ringtailsoftware

That'll do it

ringtailsoftware avatar Dec 22 '22 20:12 ringtailsoftware

Minor tweak made to allow media directory to be statically served

ringtailsoftware avatar Dec 22 '22 23:12 ringtailsoftware