跳转到主要内容

将文件附加到Kinto记录

项目描述

https://github.com/Kinto/kinto-attachment/actions/workflows/test.yml/badge.svg https://img.shields.io/pypi/v/kinto-attachment.svg

将文件附加到 Kinto记录

安装

pip install kinto-attachment

设置

在Kinto项目设置中

kinto.includes = kinto_attachment
kinto.attachment.base_url = http://cdn.service.org/files/

本地文件存储

本地存储文件

kinto.attachment.base_path = /tmp

S3文件存储

存储在Amazon S3上

kinto.attachment.aws.access_key = <AWS access key>
kinto.attachment.aws.secret_key = <AWS secret key>
kinto.attachment.aws.bucket_name = <bucket name>
kinto.attachment.aws.acl = <AWS ACL permissions|public-read>

参阅Pyramid存储

Google云存储

kinto.attachment.gcloud.credentials = <Path to the Service Accounts credentials JSON file>
kinto.attachment.gcloud.bucket_name = <bucket name>
kinto.attachment.gcloud.acl = publicRead

参阅Google云ACL权限

文件夹选项

使用此选项,文件将存储在子文件夹中。

使用{bucket_id}{collection_id}占位符按桶或集合组织文件。

kinto.attachment.folder = {bucket_id}/{collection_id}

或仅针对特定桶

kinto.attachment.resources.blog.folder = blog-assets

或特定集合

kinto.attachment.resources.blog.articles.folder = articles-images

keep_old_files选项

当设置为true时,文件在关联记录被删除或附件被替换时不会从磁盘/S3删除。

kinto.attachment.keep_old_files = true

或仅针对特定桶

kinto.attachment.resources.blog.keep_old_files = false

或特定集合

kinto.attachment.resources.blog.articles.keep_old_files = true

gzipped选项

如果您希望存储时上传的文件被gzip压缩(默认:False)

kinto.attachment.gzipped = true

或仅针对特定桶

kinto.attachment.resources.blog.gzipped = true

或特定集合

kinto.attachment.resources.blog.articles.gzipped = true

randomize选项

如果您希望上传的文件以随机名称存储(默认:True)

kinto.attachment.randomize = true

或仅针对特定桶

kinto.attachment.resources.blog.randomize = true

或特定集合

kinto.attachment.resources.blog.articles.randomize = true

extensions选项

如果您想上传不属于默认允许扩展名的文件(请参阅Pyramid扩展组(默认:default))

kinto.attachment.extensions = default+video

mimetypes选项

默认情况下,使用Python标准mimetypes模块从文件名猜测mimetype。

如果您想添加或覆盖mimetype,请使用以下设置和相关语法

kinto.attachment.mimetypes = .ftl:application/vnd.fluent;.db:application/vnd.sqlite3

默认存储桶

为了在默认存储桶上上传文件,应先启用内置的默认存储桶插件,然后再启用kinto_attachment插件。

在配置中,这意味着明确将其添加到includes中

kinto.includes = kinto.plugins.default_bucket
                 kinto_attachment

生产

  • 确保base_url可以访问(如果文件存储在本地,则指向base_path

  • 调整上传文件的最大大小(例如,NGinx中的client_max_body_size 10m;

例如,使用NGinx

server {
    listen 80;

    location /v1 {
        ...
    }

    location /files {
        root /var/www/kinto;
    }
}

API

POST /{record-url}/attachment

如果不存在,将创建底层记录。

必需

  • attachment:单个multipart编码文件

可选

  • data:设置在记录上的属性(序列化JSON)

  • permissions:设置在记录上的权限(序列化JSON)

DELETE /{record-url}/attachment

从记录中删除附件。

属性

当文件被附加时,相关的记录会被赋予一个包含以下字段的attachment属性

  • filename:原始文件名

  • hash:SHA-256十六进制摘要

  • location:附件的URL

  • mimetype:文件的媒体类型

  • size:字节数量

{
    "data": {
        "attachment": {
            "filename": "IMG_20150219_174559.jpg",
            "hash": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
            "location": "http://cdn.service.org/files/ffa9c7b9-7561-406b-b7f9-e00ac94644ff.jpg",
            "mimetype": "image/jpeg",
            "size": 1481798
        },
        "id": "c2ce1975-0e52-4b2f-a5db-80166aeca688",
        "last_modified": 1447834938251,
        "theme": "orange",
        "type": "wallpaper"
    },
    "permissions": {
        "write": ["basicauth:6de355038fd943a2dc91405063b91018bb5dd97a08d1beb95713d23c2909748f"]
    }
}

如果文件被服务器gzip压缩,则会在attachment键中添加一个original键,包含在gzip之前文件的详细信息。在这种情况下,attachment键指的是压缩后的文件

{
    "data": {
        "attachment": {
            "filename": "IMG_20150219_174559.jpg.gz",
            "hash": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
            "location": "http://cdn.service.org/files/ffa9c7b9-7561-406b-b7f9-e00ac94644ff.jpg.gz",
            "mimetype": "application/x-gzip",
            "size": 14818,
            "original": {
                "filename": "IMG_20150219_174559.jpg",
                "hash": "hPME6i9avCf/LFaznYr+sHtwQEX7mXYHSu+vgtygpM8=",
                "mimetype": "image/jpeg",
                "size": 1481798
            }
        },
        "id": "c2ce1975-0e52-4b2f-a5db-80166aeca688",
        "last_modified": 1447834938251,
        "theme": "orange",
        "type": "wallpaper"
    },
    "permissions": {
        "write": ["basicauth:6de355038fd943a2dc91405063b91018bb5dd97a08d1beb95713d23c2909748f"]
    }
}

使用方法

使用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": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
    "location": "http://cdn.service.org/files/ffa9c7b9-7561-406b-b7f9-e00ac94644ff.jpg",
    "mimetype": "image/jpeg",
    "size": 1481798
}

使用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()

使用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);
  });

脚本

本存储库中提供了两个脚本。

它们依赖于kinto-client Python包,该包可以安装在一个虚拟环境中

$ virtualenv env --python=python3
$ source env/bin/activate
$ pip install kinto-client

或者在系统上全局安装(不建议

$ sudo pip install kinto-client

上传文件

upload.py接受一个文件列表,并将它们上传到指定的服务器、存储桶和集合

$ python3 scripts/upload.py --server=$SERVER --bucket=$BUCKET --collection=$COLLECTION --auth "token:mysecret" README.rst pictures/*

如果传递了--gzip选项,则在上传之前将文件gzip压缩。由于attachment属性包含压缩文件的元数据,原始文件的元数据将存储在original属性中。

有关选项的更多信息,请参阅python3 scripts/upload.py --help

下载文件

download.py从指定的服务器、存储桶和集合下载附件,并将它们存储在磁盘上

$ python3 scripts/download.py --server=$SERVER --bucket=$BUCKET --collection=$COLLECTION --auth "token:mysecret"

如果记录具有original属性,则脚本在下载后解压缩附件。

默认情况下,文件存储在当前文件夹中。有关选项的更多信息,请参阅python3 scripts/download.py --help

已知限制

  • 不支持分块上传(#10)

  • 当服务器使用POST /v1/__flush__清除时,文件不会被删除

记录中的相对URL(解决方法)

目前,记录中返回的是完整URL。这对于API消费者来说非常方便,他们只需使用location属性中的值即可访问附加的文件。

然而,它的实现方式有一个限制:完整URL直接存储在每个记录中。这很烦人,因为更改base_url设置实际上不会更改现有记录上的location属性。

作为解决方法,可以将kinto.attachment.base_url设置为空值。现在,记录中的location属性将包含一个relative URL。

通过另一个设置kinto.attachment.extra.base_url,可以通知客户端可以预先附加的基URL以获取完整的附件URL。如果指定,它将暴露在根URL端点的功能中。

运行测试

在另一个终端运行一个模拟的Amazon S3服务器

make run-moto

运行测试套件

make tests

发布

  1. https://github.com/Kinto/kinto-attachment/releases/new上创建一个GitHub发布

  2. 创建一个新标签X.Y.Z此标签将在发布此版本时从目标创建。

  3. 生成发布说明

  4. 发布版本

注意

项目详情


下载文件

下载适用于您的平台的文件。如果您不确定选择哪一个,请了解更多关于 安装包 的信息。

源代码分发

kinto-attachment-6.4.0.tar.gz (64.9 kB 查看散列值)

上传时间 源代码

构建分发

kinto_attachment-6.4.0-py3-none-any.whl (20.7 kB 查看散列值)

上传时间 Python 3

支持者