Загрузка файлов

Загрузка файлов через API Пачки — трёхшаговый процесс с presigned URL (S3-совместимое хранилище).

Процесс загрузки

Получение параметров загрузки

Сделайте запрос к методу POSTПолучение подписи, ключа и других параметров без тела для получения подписи и параметров. Данный метод необходимо использовать для загрузки каждого файла.

Получение параметров загрузки
pachca common uploads \  --json \  --token YOUR_ACCESS_TOKEN

В ответе вы получите параметры для следующего шага: Content-Disposition, acl, policy, x-amz-credential, x-amz-algorithm, x-amz-date, x-amz-signature, key и direct_url.

Загрузка файла

Отправьте запрос к методу POSTЗагрузка файла с форматом multipart/form-data на адрес direct_url. Включите все полученные параметры и сам файл. При успешной загрузке сервер вернёт HTTP 201 Created.

Загрузка файла
# URL получается из ответа POST /uploads (поле direct_url)pachca common direct-url \  --direct-url=$DIRECT_URL \  --content-disposition=your_api_token_here \  --acl=your_api_token_here \  --policy=your_api_token_here \  --x-amz-credential=your_api_token_here \  --x-amz-algorithm=your_api_token_here \  --x-amz-date=your_api_token_here \  --x-amz-signature=your_api_token_here \  --key=your_api_token_here \  --file=./file.jpg \  --json
Порядок полей в multipart-запросе важен: файл (file) должен быть последним полем.

Прикрепление файла к сообщению или другой сущности

После загрузки файла, чтобы прикрепить его к сообщению или другой сущности API, необходимо сформировать путь файла. Для этого в поле key, полученном на этапе подписи, заменить шаблон ${filename} на фактическое имя файла.

Пример: если ваш файл называется Логотип для сайта.png, а в ответе на метод /uploads ключ был attaches/files/93746/e354-...-5e6f/${filename}, итоговый ключ будет attaches/files/93746/e354-...-5e6f/Логотип для сайта.png.

{  "message": {    "entity_type": "discussion",    "entity_id": 12345,    "content": "Документ прикреплён",    "files": [      {        "key": "attaches/files/93746/e354fd79-.../document.pdf",        "name": "document.pdf",        "file_type": "file",        "size": 102400      }    ]  }}

Через CLI

Команда pachca upload автоматически выполняет шаги 1 и 2 — получает подпись и загружает файл на S3. Возвращает готовый key:

# Загрузить файлpachca upload report.pdf # Загрузить и отправить в чатKEY=$(pachca upload report.pdf -o json | jq -r '.key')pachca messages create --entity-id 12345 \  --content "Отчёт прикреплён" \  --files "[{\"key\":\"$KEY\",\"name\":\"report.pdf\",\"file_type\":\"file\",\"size\":$(stat -f%z report.pdf)}]"

Типы файлов

Типfile_typeДополнительные поля
Файлfile
Изображениеimagewidth, height — размеры в пикселях

Примеры полного цикла

TypeScript SDK

import { PachcaClient, FileUploadRequest, FileType } from "@pachca/sdk"import fs from "fs"import path from "path" const client = new PachcaClient("YOUR_TOKEN") const filePath = "./report.pdf"const fileName = path.basename(filePath)const fileBuffer = fs.readFileSync(filePath) // Шаг 1: Получить параметры загрузкиconst params = await client.common.getUploadParams() // Шаг 2: Загрузить файл на S3 (direct_url — внешний presigned URL)await client.common.uploadFile(params.directUrl, {  contentDisposition: params.contentDisposition,  acl: params.acl,  policy: params.policy,  xAmzCredential: params.xAmzCredential,  xAmzAlgorithm: params.xAmzAlgorithm,  xAmzDate: params.xAmzDate,  xAmzSignature: params.xAmzSignature,  key: params.key,  file: new File([fileBuffer], fileName)}) // Шаг 3: Отправить сообщение с файломconst fileKey = params.key.replace("${filename}", fileName)await client.messages.createMessage({  message: {    entityType: "discussion",    entityId: 12345,    content: "Отчёт прикреплён",    files: [{ key: fileKey, name: fileName, fileType: FileType.File, size: fileBuffer.length }]  }})

Python SDK

from pachca.client import PachcaClientfrom pachca.models import FileUploadRequest, MessageCreateRequest, MessageCreateRequestMessage, MessageCreateRequestFile, FileTypeimport os client = PachcaClient("YOUR_TOKEN") file_path = "report.pdf"file_name = os.path.basename(file_path) # Шаг 1: Получить параметры загрузкиparams = await client.common.get_upload_params() # Шаг 2: Загрузить файл на S3 (direct_url — внешний presigned URL)with open(file_path, "rb") as f:    await client.common.upload_file(        direct_url=params.direct_url,        request=FileUploadRequest(            content_disposition=params.content_disposition,            acl=params.acl,            policy=params.policy,            x_amz_credential=params.x_amz_credential,            x_amz_algorithm=params.x_amz_algorithm,            x_amz_date=params.x_amz_date,            x_amz_signature=params.x_amz_signature,            key=params.key,            file=f.read()        )    ) # Шаг 3: Отправить сообщение с файломfile_key = params.key.replace("${filename}", file_name)await client.messages.create_message(MessageCreateRequest(    message=MessageCreateRequestMessage(        entity_type="discussion",        entity_id=12345,        content="Отчёт прикреплён",        files=[MessageCreateRequestFile(key=file_key, name=file_name, file_type=FileType.FILE, size=os.path.getsize(file_path))]    )))

Поля multipart-формы для S3

Все поля из ответа POSTПолучение подписи передаются на S3 как есть в multipart-форме:

ПолеОписание
Content-DispositionЗаголовок для скачивания
aclПрава доступа S3
policyBase64-кодированная политика загрузки
x-amz-credentialAWS credential
x-amz-algorithmВсегда AWS4-HMAC-SHA256
x-amz-dateДата подписи
x-amz-signatureПодпись запроса
keyПуть файла на S3 (содержит ${filename} — заменить на реальное имя)
fileСам файл — обязательно последнее поле
direct_url — это внешний presigned URL от S3. Он не является эндпоинтом Пачки, не требует заголовка Authorization и имеет ограниченное время действия.

Частые ошибки

ОшибкаПричинаРешение
403 Forbidden при загрузкеИстекла подписьПараметры загрузки действительны ограниченное время. Запросите новые через POSTПолучение подписи
400 Bad RequestНеправильный Content-TypeУбедитесь, что запрос отправляется как multipart/form-data, а не application/json
Файл не отображаетсяНеверный keyПроверьте, что ${filename} в ключе заменён на реальное имя файла