File Attachments

Attachments configure API objects, such as a user's avatar_file, a style's file or a behavior's attachment_file. To transfer a file to your site's folders, use files_sdk.upload_file().

InputBehavior
Bytes or a binary streamSends the supplied content.
files_sdk.AttachmentAlso sets the filename and content type.
Attachment.from_path(path)Opens and closes the local file for you.
StringIs never treated as a local path.
JSON file objectSends encoded_content, filename and type as supplied.

The default filename is the stream's basename, or the parameter name when unavailable. The default content type is application/octet-stream.

Example Request

import files_sdk

try:
  with open("avatar.png", "rb") as picture:
    files_sdk.user.update(1234, {
      "avatar_file": files_sdk.Attachment(picture, content_type="image/png"),
    })
  
  files_sdk.style.update("marketing/assets", {
    "file": files_sdk.Attachment.from_path("logo.png", content_type="image/png"),
  })
except files_sdk.error.NotAuthenticatedError as err:
  print(f"Authentication Error Occurred ({type(err).__name__}):", err)
except files_sdk.error.Error as err:
  print(f"Unknown Error Occurred ({type(err).__name__}):", err)

Streams and Retries

The SDK borrows your stream from its current position to the end and leaves it open. Keep it unchanged until the call returns.

SourceReplay for an allowed retry or 307/308 redirect
Seekable streamSeeks back to the starting position and sends the same bytes.
Nonseekable stream, such as a pipe or sys.stdin.bufferBuffers first: up to 1 MiB in memory, then a temporary file removed when the request ends.
Attachment.from_path()Replays only while the original size and modification time remain unchanged.

Nonseekable buffering is limited to 64 MiB per attachment by default, or its spool_limit. A request containing several attachments can buffer each one's allowance. This replay support does not make an otherwise unsafe request eligible for retry; see Retries.

Example Request

import sys

import files_sdk

try:
  files_sdk.user.update(1234, {
    "avatar_file": files_sdk.Attachment(
      sys.stdin.buffer,
      filename="avatar.png",
      content_type="image/png",
      spool_limit=16 * 1024 * 1024,
    ),
  })
except files_sdk.error.NotAuthenticatedError as err:
  print(f"Authentication Error Occurred ({type(err).__name__}):", err)
except files_sdk.error.Error as err:
  print(f"Unknown Error Occurred ({type(err).__name__}):", err)

Other Parameters

Other parameters retain their supplied values. The SDK uses multipart form data when it can preserve every value and the filename exactly; otherwise it sends a JSON file object with streamed base64 content, about one third larger.

JSON is required for None, empty lists or objects, numbers or booleans inside an object, lists of objects, or filenames containing %, \, / or ", which the API's form parser would change.

The API validates the attachment and parameters normally. The SDK raises InvalidParameterError without retrying for a text stream, read() returning None or ending early, exceeded spool limits, or a changed local file.

Example Request

import files_sdk

try:
  with open("watermark.png", "rb") as image:
    files_sdk.behavior.create({
      "path": "shared/previews",
      "behavior": "watermark",
      "attachment_file": files_sdk.Attachment(image, content_type="image/png"),
      "value": {
        "gravity": "SouthWest",
        "max_height_or_width": 20,
        "transparency": 25,
      },
    })
except files_sdk.error.NotAuthenticatedError as err:
  print(f"Authentication Error Occurred ({type(err).__name__}):", err)
except files_sdk.error.Error as err:
  print(f"Unknown Error Occurred ({type(err).__name__}):", err)