File size: 2,133 Bytes
6cddd31
 
 
 
 
 
d6dd38f
6cddd31
d6dd38f
6cddd31
 
 
 
 
d6dd38f
 
6cddd31
 
 
 
d6dd38f
6cddd31
 
 
d6dd38f
 
 
6cddd31
 
d6dd38f
 
 
 
 
6cddd31
d6dd38f
6cddd31
d6dd38f
 
6cddd31
 
 
 
 
 
 
 
 
 
 
 
 
d6dd38f
 
 
 
 
 
 
 
 
 
 
6cddd31
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
from fastapi import FastAPI, UploadFile, File, Form, HTTPException
from fastapi.responses import StreamingResponse
import subprocess
import io
import os
from typing import Optional
from urllib.parse import urlparse

app = FastAPI()

@app.post("/process")
async def process_image(
    file: Optional[UploadFile] = File(None),
    url: Optional[str] = Form(None),
    options: Optional[str] = Form("-q:v 2"),
    filename: Optional[str] = Form(None) # 新增:支持自定义文件名
):
    input_source = ""
    input_data = None

    # 1. 确定输入源
    if file:
        input_data = await file.read()
        input_source = "pipe:0"
        # 如果没传 filename,则使用上传文件的原始名,但后缀改为 .jpg
        if not filename:
            filename = os.path.splitext(file.filename)[0] + ".jpg"
    elif url:
        input_source = url
        # 如果没传 filename,从 URL 中解析文件名,后缀改为 .jpg
        if not filename:
            path = urlparse(url).path
            base_name = os.path.basename(path) or "downloaded_image"
            filename = os.path.splitext(base_name)[0] + ".jpg"
    else:
        raise HTTPException(status_code=400, detail="Missing source")

    # 2. 执行 FFmpeg 转换 (PNG -> JPG)
    command = ['ffmpeg', '-i', input_source]
    if options:
        command.extend(options.split())
    command.extend(['-f', 'image2', 'pipe:1'])

    try:
        process = subprocess.Popen(
            command,
            stdin=subprocess.PIPE if input_data else None,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE
        )
        out, err = process.communicate(input=input_data)

        # 3. 构建响应,添加 Content-Disposition Header
        # 这会让 n8n 和浏览器识别出文件名
        headers = {
            'Content-Disposition': f'attachment; filename="{filename}"'
        }
        
        return StreamingResponse(
            io.BytesIO(out), 
            media_type="image/jpeg", 
            headers=headers
        )

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))