Attach files to Kinto records
Project description
proof-of-concept: Attach files to Kinto records.
Install
pip install kinto-attachment
Setup
In the Kinto project settings
kinto.includes = kinto_attachment kinto.attachment.base_url = http://cdn.service.org/files/ kinto.attachment.folder = {bucket_id}/{collection_id}
Store files locally:
kinto.attachment.base_path = /tmp
Store on Amazon S3:
kinto.attachment.aws.access_key = <AWS access key> kinto.attachment.aws.secret_key = <AWS secret key> kinto.attachment.aws.bucket = <bucket name> kinto.attachment.aws.acl = <AWS ACL permissions|public-read>
See Pyramid Storage.
Production
Make sure the base_url can be reached (and points to base_path if files are stored locally)
Adjust the max size for uploaded files (e.g. client_max_body_size 10m; for NGinx)
For example, with NGinx
server { listen 80; location /v1 { ... } location /files { root /var/www/kinto; } }
API
POST /{record-url}/attachment
It will create the underlying record if it does not exist.
Required
attachment: a single multipart-encoded file
Optional
data: attributes to set on record (serialized JSON)
permissions: permissions to set on record (serialized JSON)
DELETE /{record-url}/attachment
Deletes the attachement from the record.
Attributes
When a file is attached, the related record is given an attachment attribute with the following fields:
filename: the original filename
hash: a SHA-256 digest
location: the URL of the attachment
mimetype: the media type of the file
size: size in bytes
{ "data": { "attachment": { "filename": "IMG_20150219_174559.jpg", "hash": "hPME6i9avCf/LFaznYr+sHtwQEX7mXYHSu+vgtygpM8=", "location": "http://cdn.service.org/files/ffa9c7b9-7561-406b-b7f9-e00ac94644ff.jpg", "mimetype": "text/plain", "size": 1481798 }, "id": "c2ce1975-0e52-4b2f-a5db-80166aeca688", "last_modified": 1447834938251, "theme": "orange", "type": "wallpaper" }, "permissions": { "write": ["basicauth:6de355038fd943a2dc91405063b91018bb5dd97a08d1beb95713d23c2909748f"] } }
Usage
Using HTTPie
http --auth alice:passwd --form POST http://localhost:8888/v1/buckets/website/collections/assets/records/c2ce1975-0e52-4b2f-a5db-80166aeca689/attachment data='{"type": "wallpaper", "theme": "orange"}' "attachment@~/Pictures/background.jpg" HTTP/1.1 201 Created Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff Content-Length: 209 Content-Type: application/json; charset=UTF-8 Date: Wed, 18 Nov 2015 08:22:18 GMT Etag: "1447834938251" Last-Modified: Wed, 18 Nov 2015 08:22:18 GMT Location: http://localhost:8888/v1/buckets/website/collections/font/assets/c2ce1975-0e52-4b2f-a5db-80166aeca689 Server: waitress { "filename": "IMG_20150219_174559.jpg", "hash": "hPME6i9avCf/LFaznYr+sHtwQEX7mXYHSu+vgtygpM8=", "location": "http://cdn.service.org/files/ffa9c7b9-7561-406b-b7f9-e00ac94644ff.jpg", "mimetype": "text/plain", "size": 1481798 }
Using Python requests
auth = ("alice", "passwd") attributes = {"type": "wallpaper", "theme": "orange"} perms = {"read": ["system.Everyone"]} files = [("attachment", ("background.jpg", open("Pictures/background.jpg", "rb"), "image/jpeg"))] payload = {"data": json.dumps(attributes), "permissions": json.dumps(perms)} response = requests.post(SERVER_URL + endpoint, data=payload, files=files, auth=auth) response.raise_for_status()
Using JavaScript
var headers = {Authorization: "Basic " + btoa("alice:passwd")}; var attributes = {"type": "wallpaper", "theme": "orange"}; var perms = {"read": ["system.Everyone"]}; // File object from input field var file = form.elements.attachment.files[0]; // Build form data var payload = new FormData(); // Multipart attachment payload.append('attachment', file, "background.jpg"); // Record attributes and permissions JSON encoded payload.append('data', JSON.stringify(attributes)); payload.append('permissions', JSON.stringify(perms)); // Post form using GlobalFetch API var url = `${server}/buckets/${bucket}/collections/${collection}/records/${record}/attachment`; fetch(url, {method: "POST", body: payload, headers: headers}) .then(function (result) { console.log(result); });
Known limitations
Because boto is used for Amazon S3, this plugin is only compatible with Python 2
Currently only Python 2.7 is tested/supported (#27)
No support for chunk upload (#10)
Fails when uploading files to default bucket (see Kinto/kinto#277)
Files are not removed when server is purged with POST /v1/__purge__
Absolute URL is stored in record metadata (#24)
Run tests
Run a fake Amazon S3 server in a separate terminal:
make moto
Run the tests suite:
make tests
Notes
API design discussion about mixing up attachment and record fields.
Changelog
0.3.0 (2016-02-05)
New feature
Expose the API capability attachments in the root URL (#35)
Internal changes
Upgrade tests for Kinto 1.11.0 (#36)
0.2.0 (2015-12-21)
New feature
Setting to store files into folders by bucket or collection (fixes #22)
Bug fixes
Remove existing file when attachment is replaced (fixes #28)
Documentation
The demo is now fully online, since the Mozilla demo server has this plugin installed.
Add some minimal information for production
0.1.0 (2015-12-02)
Initial working proof-of-concept.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for kinto_attachment-0.3.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 21d63280d7b555aa00b2e383c4dc909f9ee3098b4c8eae9e81277b9d263b13b5 |
|
MD5 | 14aee2be8fb74abf207d20785d224e59 |
|
BLAKE2b-256 | be29b8b7653eeb71d175a93a0779290f788f2f261204abf9eb2664b64cfb2961 |