Metadata-Version: 2.4
Name: image-upload
Version: 0.1.0
Summary: Image Upload Package for FastAPI
Author-email: Sahil Sheoran <sahilsheoran24@gmail.com>
License-Expression: MIT
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: aiofiles>=25.1.0
Requires-Dist: fastapi>=0.138.2
Requires-Dist: pydantic>=2.13.4
Dynamic: license-file

# image-upload

A lightweight FastAPI package for saving uploaded files and generating absolute URLs for stored images using Pydantic.

## Features

* Simple file upload handling
* Automatically stores files inside an `uploads/` directory
* Returns the saved file path
* Easily generate absolute URLs with Pydantic
* Asynchronous file saving using `aiofiles`
* File size and MIME type validation

---

## Requirements

- Python 3.12+
- FastAPI
- Pydantic v2
- aiofiles

---

## Installation

Install from PyPI:

```bash
pip install image-upload
```

---

## Supported File Types

By default the package accepts:

- JPEG (`image/jpeg`)
- PNG (`image/png`)
- GIF (`image/gif`)
- PDF (`application/pdf`)
- Plain Text (`text/plain`)

Maximum upload size is **50 MB**.

---

## Saving an Uploaded File

Import `get_path` and pass an `UploadFile`.

```python
from image_upload import get_path

data.picture = await get_path(data.picture)
```

or

```python
data["picture"] = await get_path(data.pop("picture"))
```

The function returns the relative storage path.

Example output:

```text
uploads/0c6d8a69-9c84-47d4-81f6-d15d11fcbf88.png
```

---

## FastAPI Example

```python
from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession

from image_upload import get_path

router = APIRouter()

@router.post("/")
async def create(
    data: UserCreate = Depends(UserCreate.as_form),
    db: AsyncSession = Depends(get_db),
):
    data.picture = await get_path(data.picture)

    return await user(db, data.model_dump())
```

---

## Save Inside a Custom Folder

You can optionally provide a folder name.

```python
path = await get_path(file, folder="users")
```

---

## Building Absolute URLs

`AbsoluteUrl` automatically prepends the application's base URL using the Pydantic validation context.

```python
from pydantic import BaseModel
from image_upload import AbsoluteUrl

class UserOut(BaseModel):
    name: str
    picture: AbsoluteUrl
```

When validating:

```python
user = UserOut.model_validate(
    data,
    context={
        "base_url": "https://example.com/"
    }
)
```

## Note: Can also use "base_url": request.base_url

```python
from fastapi import Request

@router.get("/")
async def get_user(
    request: Request,
    db: AsyncSession = Depends(get_db),
) -> UserOut:
    users = await list_user(
        db
    )

    return UserOut.model_validate(
        users,
        context={"base_url": request.base_url},
    )

```

Result:

```json
{
    "name": "John",
    "picture": "https://example.com/uploads/avatar.png"
}
```

---

## API

### `get_path(file, folder=None)`

Stores the uploaded file and returns its storage path.

**Parameters**

| Parameter | Type        | Description             |
|-----------|-------------|-------------------------|
| file      | UploadFile  | Uploaded file           |
| folder    | str | None  | Optional folder prefix  |

**Returns**

```python
str
```

Example:

```python
path = await get_path(upload_file)
```

---

## Security

The package performs basic validation:

- Allowed MIME type validation
- Maximum file size validation (50 MB)
- UUID-based file names to avoid collisions
- Asynchronous streaming to reduce memory usage

---

## Dependencies

- FastAPI
- Pydantic v2
- aiofiles

---

## License

MIT License
