Skip to main content

Uploader (Python)

Port em Python do pacote PHP coffeecode/uploader de Robson V. Leite. Mantem o comportamento original (validacao por mime/extensao, diretorios YYYY/MM, slug, redimensionamento de imagens) com uma API framework-agnostica baseada em UploadedFile — aceita path em disco ou stream em memoria, com adapters prontos para Flask e FastAPI.

Python port of the PHP package coffeecode/uploader by Robson V. Leite. Same behavior (mime/extension validation, year/month directories, slugged filenames, image resizing) with a framework-agnostic UploadedFile API: accepts a filesystem path or an in-memory stream, with built-in adapters for Flask and FastAPI.

Destaques

  • Upload simples de imagens, arquivos e midias
  • UploadedFile: abstracao unica para path em disco ou stream
  • Adapters: from_flask, from_fastapi, from_stream, from_path, from_dict (compat com PHP $_FILES)
  • Gestao de diretorios com esquema de datas (YYYY/MM)
  • Validacao por mime-type e extensao
  • Redimensionamento e qualidade de imagem (substitui ext-gd por Pillow)

Instalacao

pip install coffeecode-uploader

Requer Python >= 3.9 e Pillow >= 10.

Uso

Flask

from flask import Flask, request
from coffeecode_uploader import Image, UploadedFile, UploaderException

@app.post("/avatar")
def avatar():
    try:
        upload = UploadedFile.from_flask(request.files["image"])
        path = Image("uploads", "images").upload(upload, request.form["name"])
        return {"path": path}
    except UploaderException as e:
        return {"error": str(e)}, 400

FastAPI

from fastapi import FastAPI, File, UploadFile, HTTPException
from coffeecode_uploader import Image, UploadedFile, UploaderException

app = FastAPI()

@app.post("/avatar")
async def avatar(name: str, image: UploadFile = File(...)):
    try:
        upload = UploadedFile.from_fastapi(image)
        path = Image("uploads", "images").upload(upload, name)
        return {"path": path}
    except UploaderException as e:
        raise HTTPException(400, str(e))

Stream em memoria

from io import BytesIO
from coffeecode_uploader import File, UploadedFile

upload = UploadedFile.from_stream(
    BytesIO(pdf_bytes),
    filename="report.pdf",
    content_type="application/pdf",
)
path = File("uploads", "files").upload(upload, "Relatorio Mensal")

Path ja em disco

from coffeecode_uploader import File, UploadedFile

upload = UploadedFile.from_path("/tmp/report.pdf", content_type="application/pdf")
path = File("uploads", "files").upload(upload, "Relatorio")

Compat com $_FILES (PHP-style)

from coffeecode_uploader import File, UploadedFile

upload = UploadedFile.from_dict({
    "name": "report.pdf",
    "type": "application/pdf",
    "tmp_name": "/tmp/upload.pdf",
})
path = File("uploads", "files").upload(upload, "Relatorio")

API

Construtores

Image(upload_dir, file_type_dir, month_year_path=True)
File(upload_dir, file_type_dir, month_year_path=True)
Media(upload_dir, file_type_dir, month_year_path=True)
Send(upload_dir, file_type_dir, allow_types, extensions, month_year_path=True)

upload(file: UploadedFile, name: str, ...)

Retorna a string com o caminho final relativo. Lanca UploaderException quando o tipo MIME ou a extensao nao estao na lista permitida.

  • Image.upload(image, name, width=2000, quality=None) — quality aceita {"jpg": 0..95, "png": 0..9}. Padrao: {"jpg": 75, "png": 5}. GIFs sao copiados sem reprocessamento (igual ao PHP).
  • File.upload(file, name)
  • Media.upload(media, name)
  • Send.upload(file, name)

UploadedFile

Metodo Quando usar
UploadedFile.from_flask(file_storage) request.files["x"] em Flask/Quart
UploadedFile.from_fastapi(upload_file) UploadFile em FastAPI/Starlette
UploadedFile.from_stream(stream, ...) BytesIO, S3 body, qualquer file-like binario
UploadedFile.from_path(path, content_type) Arquivo ja em disco
UploadedFile.from_dict({...}) Compat com $_FILES PHP
.open() Context manager → file-like binario
.save_to(dst) Copia para dst (preserva o source)
.extension Extensao em lowercase a partir de filename

Helpers

  • Cls.is_allowed() (alias Cls.isAllowed()) — lista de mime-types permitidos.
  • Cls.is_extension() (alias Cls.isExtension()) — lista de extensoes permitidas.
  • Uploader.multiple([...]) — converte lista heterogenea (dict, FileStorage, UploadFile, UploadedFile) em list[UploadedFile].

Migrar de v1.x

A v1 aceitava um dict no formato PHP $_FILES. Em v2 use UploadedFile:

# v1
file_dict = {"name": "x.pdf", "type": "application/pdf", "tmp_name": "/tmp/x"}
File("uploads", "files").upload(file_dict, "Doc")

# v2
upload = UploadedFile.from_dict(file_dict)
File("uploads", "files").upload(upload, "Doc")

Equivalencia com a versao PHP

PHP Python
CoffeeCode\Uploader\Image coffeecode_uploader.Image
CoffeeCode\Uploader\File coffeecode_uploader.File
CoffeeCode\Uploader\Media coffeecode_uploader.Media
CoffeeCode\Uploader\Send coffeecode_uploader.Send
Exception UploaderException
$_FILES['x'] UploadedFile.from_dict({...})
move_uploaded_file() UploadedFile.save_to()
ext-gd Pillow
monthYearPath month_year_path

Creditos

  • API e comportamento original: Robson V. Leite — coffeecode/uploader (MIT)
  • Port Python: Kaue Leal

Licenca

MIT.

Release files for coffeecode-uploader 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for coffeecode-uploader 2.0.0
File Size Uploaded
coffeecode_uploader-2.0.0.tar.gz 14.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for coffeecode-uploader 2.0.0
File Interpreter ABI Platform
coffeecode_uploader-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 24.8 kB

Release files / coffeecode_uploader-2.0.0.tar.gz

Download URL coffeecode_uploader-2.0.0.tar.gz
Size 14.2 kB
Tags Source
SHA-256 checksum
How to use checksums
0c32e3dbcb4c2943c66193f13b536f5134630b2e8bc2dc239ceeca714fcb7907
BLAKE2b-256 checksum
How to use checksums
222d9be631553852d3722e85e9f7a14732b2c955b67be53404488688c0a8c370
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 30, 2026.

Transparency log

Release files / coffeecode_uploader-2.0.0-py3-none-any.whl

Download URL coffeecode_uploader-2.0.0-py3-none-any.whl
Size 10.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
85388ebbf14ef3a6fb562f8ea4920662c55e144f45493cfdfe714e63b30663c5
BLAKE2b-256 checksum
How to use checksums
82ffcb8e79cb369f6912385b78fb8499de559eba62e48581037cdfe99182e98c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page