回應格式處理
FastAPI 可以透過不同的 Response 類別,回應 JSON、純文字、HTML 或檔案內容給前端。
## 1. JSON 格式
JSON 是最常見的 API 回應格式,前端通常使用 `fetch()` 或 Axios 接收。
### 直接回傳 `dict` 或 `list`
FastAPI 會自動將 Python 的 `dict`、`list` 等資料轉成 JSON。
```python
from fastapi import FastAPI
app = FastAPI()
@app.get("/user")
def get_user():
return {
"id": 1,
"name": "Alice",
"email": "alice@example.com"
}
```
回應內容:
```json
{
"id": 1,
"name": "Alice",
"email": "alice@example.com"
}
```
### 使用 `JSONResponse`
如果需要指定狀態碼、標頭或自訂回應,可以使用 `JSONResponse`。
```python
from fastapi import FastAPI
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/success")
def success():
return JSONResponse(
content={
"message": "操作成功",
"data": [1, 2, 3]
},
status_code=200
)
```
也可以回傳錯誤狀態:
```python
@app.get("/error")
def error():
return JSONResponse(
content={"message": "找不到資料"},
status_code=404
)
```
前端使用 `fetch()`:
```javascript
fetch("/user")
.then(response => response.json())
.then(data => {
console.log(data.name);
});
```
---
## 2. 純文字格式
使用 `PlainTextResponse` 回傳 `text/plain`。
```python
from fastapi.responses import PlainTextResponse
@app.get("/hello-text", response_class=PlainTextResponse)
def hello_text():
return "Hello, FastAPI!"
```
回應標頭通常會是:
```http
Content-Type: text/plain; charset=utf-8
```
也可以直接建立 Response:
```python
@app.get("/message")
def message():
return PlainTextResponse(
content="這是一段純文字",
status_code=200
)
```
前端接收純文字:
```javascript
fetch("/hello-text")
.then(response => response.text())
.then(text => {
console.log(text);
});
```
---
## 3. HTML 格式
使用 `HTMLResponse` 回傳 HTML 內容。
```python
from fastapi.responses import HTMLResponse
@app.get("/page", response_class=HTMLResponse)
def page():
return """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>FastAPI Page</title>
</head>
<body>
<h1>Hello FastAPI</h1>
<p>這是 HTML 回應。</p>
</body>
</html>
"""
```
回應標頭:
```http
Content-Type: text/html; charset=utf-8
```
瀏覽器直接開啟:
```text
http://localhost:8000/page
```
就會將內容解析成網頁。
也可以手動建立:
```python
@app.get("/html")
def html():
return HTMLResponse(
content="<h1>歡迎使用 FastAPI</h1>",
status_code=200
)
```
---
## 4. 回傳檔案內容
FastAPI 常見的檔案回應方式有兩種:
- `FileResponse`:直接回傳伺服器上的檔案
- `StreamingResponse`:串流回傳檔案或動態產生的內容
---
### 4.1 使用 `FileResponse`
假設專案中有:
```text
project/
├── main.py
└── files/
└── example.pdf
```
程式碼:
```python
from fastapi import FastAPI
from fastapi.responses import FileResponse
app = FastAPI()
@app.get("/download")
def download_file():
return FileResponse(
path="files/example.pdf",
filename="example.pdf",
media_type="application/pdf"
)
```
瀏覽器通常會依照 `Content-Disposition` 決定下載或開啟檔案。
常見 `media_type`:
```text
application/pdf
image/png
image/jpeg
text/csv
application/zip
application/octet-stream
```
如果希望強制下載,可以指定 `Content-Disposition`:
```python
from fastapi.responses import FileResponse
@app.get("/download-pdf")
def download_pdf():
return FileResponse(
path="files/example.pdf",
filename="report.pdf",
media_type="application/pdf",
content_disposition_type="attachment"
)
```
如果希望瀏覽器嘗試直接開啟,例如 PDF 或圖片,可以使用:
```python
@app.get("/view-pdf")
def view_pdf():
return FileResponse(
path="files/example.pdf",
filename="example.pdf",
media_type="application/pdf",
content_disposition_type="inline"
)
```
---
### 4.2 回傳圖片
```python
@app.get("/image")
def get_image():
return FileResponse(
path="files/photo.png",
media_type="image/png"
)
```
前端可以直接設定圖片網址:
```html
<img src="/image" alt="圖片">
```
或使用 JavaScript:
```javascript
const image = document.querySelector("img");
image.src = "/image";
```
---
### 4.3 使用 `StreamingResponse`
當檔案很大,或內容是動態產生時,可以使用串流方式。
```python
from fastapi.responses import StreamingResponse
def file_iterator(path: str):
with open(path, "rb") as file:
while chunk := file.read(1024 * 1024):
yield chunk
@app.get("/stream-file")
def stream_file():
return StreamingResponse(
file_iterator("files/large.zip"),
media_type="application/zip",
headers={
"Content-Disposition": 'attachment; filename="large.zip"'
}
)
```
這種方式不需要一次將整個檔案載入記憶體。
---
## 5. 自訂 HTTP 標頭與狀態碼
所有 Response 都可以自訂狀態碼與 HTTP 標頭。
```python
from fastapi.responses import JSONResponse
@app.get("/custom-response")
def custom_response():
return JSONResponse(
content={"message": "成功"},
status_code=201,
headers={
"X-App-Version": "1.0",
"Cache-Control": "no-cache"
}
)
```
---
## 6. 使用 `response_model` 定義 JSON 格式
如果希望限制或驗證 JSON 回應格式,可以搭配 Pydantic Model。
```python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
id: int
name: str
@app.get("/user-model", response_model=User)
def get_user_model():
return {
"id": 1,
"name": "Alice",
"extra_field": "會被過濾"
}
```
回應會符合 `User` 定義:
```json
{
"id": 1,
"name": "Alice"
}
```
---
## 7. 常用 Response 類別整理
| Response 類別 | Content-Type | 用途 |
|---|---|---|
| 直接回傳 `dict`、`list` | `application/json` | JSON API |
| `JSONResponse` | `application/json` | 自訂 JSON、狀態碼、標頭 |
| `PlainTextResponse` | `text/plain` | 純文字 |
| `HTMLResponse` | `text/html` | HTML 網頁 |
| `FileResponse` | 依檔案類型 | 回傳伺服器上的檔案 |
| `StreamingResponse` | 自訂 | 大檔案或串流內容 |
一個完整範例:
```python
from fastapi import FastAPI
from fastapi.responses import (
JSONResponse,
PlainTextResponse,
HTMLResponse,
FileResponse
)
app = FastAPI()
@app.get("/json")
def json_response():
return {"message": "JSON response"}
@app.get("/text", response_class=PlainTextResponse)
def text_response():
return "Plain text response"
@app.get("/html", response_class=HTMLResponse)
def html_response():
return "<h1>HTML response</h1>"
@app.get("/file")
def file_response():
return FileResponse(
"files/example.pdf",
filename="example.pdf",
media_type="application/pdf"
)
```
重點是:FastAPI 會根據不同的 Response 類別設定適當的 `Content-Type`,前端則依照資料格式使用 `response.json()`、`response.text()`,或直接將 URL 當作檔案、圖片或網頁來源使用。
相關學習地圖、教學課程
Python 後端工程、資料庫