Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: #50
This commit was merged in pull request #50.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
wrapperVersion=3.3.4
|
||||
distributionType=only-script
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.15/apache-maven-3.9.15-bin.zip
|
||||
distributionSha256Sum=b0d9292f06c5faded31ddcb6cb69099f316d6fea40a7778624b259bad9fed18a
|
||||
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.drinkool</groupId>
|
||||
<artifactId>drinkool</artifactId>
|
||||
<version>1.5.24</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>file-service</artifactId>
|
||||
|
||||
<properties>
|
||||
<quarkus.container-image.registry>vps.demonkernel.io.vn</quarkus.container-image.registry>
|
||||
<quarkus.container-image.group>foodsurf</quarkus.container-image.group>
|
||||
<quarkus.container-image.name>file-service</quarkus.container-image.name>
|
||||
<quarkus.container-image.push>true</quarkus.container-image.push>
|
||||
|
||||
<python.image.full.name>
|
||||
${quarkus.container-image.registry}/${quarkus.container-image.group}/${quarkus.container-image.name}</python.image.full.name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-container-image-docker</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>docker-build-python</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<executable>docker</executable>
|
||||
<workingDirectory>${project.basedir}/python</workingDirectory>
|
||||
<arguments>
|
||||
<argument>build</argument>
|
||||
<argument>-t</argument>
|
||||
<argument>${python.image.full.name}:${parent.version}</argument>
|
||||
<argument>-t</argument>
|
||||
<argument>${python.image.full.name}:latest</argument>
|
||||
<argument>.</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>push-python-image</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>quarkus.container-image.push</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>docker-push-python</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<executable>docker</executable>
|
||||
<arguments>
|
||||
<argument>push</argument>
|
||||
<argument>${python.image.full.name}</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -0,0 +1,32 @@
|
||||
# --- Stage 1: Build (Cài đặt thư viện) ---
|
||||
FROM python:3.9-slim AS builder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Khởi tạo môi trường ảo để tách biệt thư viện
|
||||
RUN python -m venv /opt/venv
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --upgrade --no-cache-dir -r requirements.txt
|
||||
|
||||
|
||||
# --- Stage 2: Runtime (Chỉ chạy Prod) ---
|
||||
FROM python:3.9-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Chỉ copy môi trường ảo đã build xong từ Stage 1
|
||||
COPY --from=builder /opt/venv /opt/venv
|
||||
ENV PATH="/opt/venv/bin:$PATH"
|
||||
|
||||
# Copy mã nguồn
|
||||
COPY main.py .
|
||||
|
||||
# Tạo folder lưu ảnh và phân quyền (tăng tính bảo mật)
|
||||
RUN mkdir images && chmod 777 images
|
||||
|
||||
# Chạy bằng Uvicorn với chế độ production (tắt reload)
|
||||
# Port 80 theo yêu cầu trước đó của bạn
|
||||
EXPOSE 80
|
||||
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80", "--workers", "4"]
|
||||
@@ -0,0 +1,52 @@
|
||||
import uuid
|
||||
import io
|
||||
from fastapi import FastAPI, Request, HTTPException
|
||||
from fastapi.responses import FileResponse
|
||||
from pathlib import Path
|
||||
from PIL import Image
|
||||
import filetype
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
STORAGE_DIR = Path("images")
|
||||
STORAGE_DIR.mkdir(exist_ok=True)
|
||||
|
||||
|
||||
@app.post("/")
|
||||
async def upload_image(request: Request):
|
||||
body = await request.body()
|
||||
|
||||
if not body:
|
||||
raise HTTPException(status_code=400, detail="Dữ liệu trống")
|
||||
|
||||
kind = filetype.guess(body)
|
||||
if kind is None or not kind.mime.startswith("image/"):
|
||||
mime_type = kind.mime if kind else "không xác định"
|
||||
raise HTTPException(
|
||||
status_code=400, detail=f"Định dạng {mime_type} không được hỗ trợ"
|
||||
)
|
||||
|
||||
try:
|
||||
img = Image.open(io.BytesIO(body))
|
||||
|
||||
random_filename = f"{uuid.uuid4()}.webp"
|
||||
file_path = STORAGE_DIR / random_filename
|
||||
|
||||
img.save(file_path, format="WEBP", quality=80)
|
||||
|
||||
return {
|
||||
"status": "success",
|
||||
"filename": random_filename,
|
||||
"original_type": kind.mime,
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Lỗi xử lý ảnh: {str(e)}")
|
||||
|
||||
|
||||
@app.get("/{name}")
|
||||
async def get_image(name: str):
|
||||
file_path = STORAGE_DIR / name
|
||||
if not file_path.exists():
|
||||
raise HTTPException(status_code=404, detail="NotFoundImage")
|
||||
return FileResponse(file_path, media_type="image/webp")
|
||||
@@ -0,0 +1,5 @@
|
||||
fastapi
|
||||
uvicorn
|
||||
python-multipart
|
||||
Pillow
|
||||
filetype
|
||||
Reference in New Issue
Block a user