# Upload API

This page documents the request format, filename generation, and responses of `POST /upload/*path`.

## Request

```bash
curl -X POST -F "filepath=@./photo.jpg" http://localhost:8080/upload/blog/2025
```

| Item | Rule |
|---|---|
| `*path` | Target folder relative to `storage/image/upload/`; created if missing; empty returns `400` |
| Form field | `filepath` (`multipart/form-data`) |
| Type check | Uses the part's `Content-Type` header; file contents are not inspected |
| Supported types | `image/jpeg`, `image/jpg`, `image/png`, `image/webp`, `image/svg+xml`, `application/pdf` |
| Size limit | None in Go; Nginx `client_max_body_size 100M` |

## Filenames

Uploads are always renamed to `{16 alphanumerics}_{millisecond timestamp}{extension}`, with the extension chosen by `GetExtension` from the MIME type (`image/jpeg` and `image/jpg` both become `.jpg`). The random characters come from `math/rand`, seeded with the current time at startup.

## Responses

Success returns `201`:

```json
{
  "success": 1,
  "filename": "ERftP1gTS7WCTeJ8_1744080848530.jpg",
  "type": "image/jpeg",
  "size": 2501808,
  "src": "http://localhost:8080/c/img/blog/2025/ERftP1gTS7WCTeJ8_1744080848530.jpg"
}
```

`configs.GetDomain()` sets the domain in `src`: `http://localhost:{PORT}` when `GO_ENV=development`, otherwise `https://{DOMAIN}`.

| Status | Body | Case |
|---|---|---|
| `400` | `please assign a path first` | Empty `*path` |
| `400` | `can not create folder: ...` | Folder creation failed |
| `400` | `can not get file form request` | Missing `filepath` field |
| `400` | `can not save file` | Write failed |
| `500` | gin Recovery default response | Unsupported type (see [Known Limitations](/known-limitations)) |
| `408` | `timed out` | Exceeded 30 seconds |
