一、项目概述

本项目通过Python的Flask框架搭建了一个简单的Web应用,利用PIL(Python Imaging Library)库实现图片的压缩和处理功能。用户可以通过Web界面上传图片,并选择是否对图片进行等比例缩放至指定分辨率,处理后的图片将以WebP格式保存并提供下载。同时,介绍了如何在1Panel平台上部署该应用。

二、代码实现

(一)Python后端代码

from flask import Flask, request, render_template, send_from_directory
from PIL import Image
import io
import os
import time
import platform

app = Flask(__name__)
UPLOAD_FOLDER = 'uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)


def resize_image(image, target_width, target_height):
    width, height = image.size
    if width / height > target_width / target_height:
        new_height = int(height * target_width / width)
        new_width = target_width
    else:
        new_width = int(width * target_height / height)
        new_height = target_height
    return image.resize((new_width, new_height), Image.LANCZOS)


@app.route('/', methods=['GET', 'POST'])
def index():
    output_file = None
    if request.method == 'POST':
        if 'image' not in request.files:
            return render_template('index.html', error='No file part')
        image_file = request.files['image']
        if image_file.filename == '':
            return render_template('index.html', error='No file selected')
        if image_file:
            try:
                image = Image.open(io.BytesIO(image_file.read()))
                image = image.convert('RGB')
                scale_enabled = request.form.get('scale_enabled')
                target_resolution_str = request.form.get('target_resolution')
                if scale_enabled and target_resolution_str:
                    try:
                        target_width_str, target_height_str = target_resolution_str.split('*')
                        target_width = int(target_width_str)
                        target_height = int(target_height_str)
                        image = resize_image(image, target_width, target_height)
                    except ValueError:
                        return render_template('index.html', error='请输入正确格式的分辨率参数(格式如:宽度*高度)。')
                else:
                    target_width = None
                    target_height = None
                if target_width is not None and target_height is not None:
                    # 创建一个具有目标分辨率的BufferedImage
                    new_image = Image.new('RGB', (target_width, target_height), (255, 255, 255))  # 白色背景
                    x = (target_width - image.size[0]) // 2
                    y = (target_height - image.size[1]) // 2
                    new_image.paste(image, (x, y))
                    image = new_image

                file_name = f'lo_{time.strftime("%Y%m%d%H%M%S")}.webp'
                output_file = os.path.join(app.config['UPLOAD_FOLDER'], file_name)
                image.save(output_file, format='webp', quality=80)
                return render_template('index.html', success=f"图片已成功压缩并保存为: {file_name}", output_file=file_name)
            except Exception as e:
                return render_template('index.html', error=f"操作失败: {e}")
    return render_template('index.html', output_file=output_file)


@app.route('/download/<filename>')
def download(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)


if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

上述代码主要实现了以下功能:

  1. 初始化Flask应用:设置了上传文件的保存目录,并在目录不存在时创建它。
  2. 图片缩放函数resize_image函数根据目标宽高对图片进行等比例缩放,保持图片的宽高比。
  3. 处理上传请求:在 index视图函数中,处理用户上传的图片。检查是否有文件上传、文件名是否为空,然后打开图片并转换为RGB模式。根据用户是否选择缩放以及输入的目标分辨率对图片进行处理,最后将处理后的图片以WebP格式保存,并返回成功信息。
  4. 下载功能download视图函数允许用户从服务器下载处理后的图片。

(二)前端HTML代码

<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>图片压缩工具</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            background-color: #f4f7fb;
        }

     .container {
            background-color: #ffffff;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            max-width: 600px;
            margin: 0 auto;
        }

        h1 {
            color: #333;
            text-align: center;
        }

        form {
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        input[type="file"],
        input[type="text"] {
            margin: 10px 0;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            width: 80%;
            max-width: 400px;
        }

        button {
            padding: 10px 20px;
            background-color: #4caf50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin-top: 10px;
        }

        button:hover {
            background-color: #45a049;
        }

     .error {
            color: red;
            margin-top: 10px;
            text-align: center;
        }

     .success {
            color: green;
            margin-top: 10px;
            text-align: center;
        }

     .checkbox-container {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }

     .checkbox-container input[type="checkbox"] {
            margin-right: 5px;
        }

        a.download-link {
            display: block;
            margin-top: 10px;
            text-align: center;
            color: #007bff;
            text-decoration: none;
        }

        a.download-link:hover {
            text-decoration: underline;
        }
    </style>
</head>

<body>
<div class="container">
    <h1>图片压缩工具</h1>
    <form method="post" enctype="multipart/form-data">
        <input type="file" name="image" accept="image/*" required>
        <div class="checkbox-container">
            <input type="checkbox" name="scale_enabled">
            <label>开启等比例缩放</label>
        </div>
        <input type="text" name="target_resolution" placeholder="请输入目标分辨率(宽度*高度),默认1612*921" value="1612*921">
        <button type="submit">压缩图片</button>
    </form>
    {% if error %}
    <p class="error">{{ error }}</p>
    {% endif %}
    {% if success %}
    <p class="success">{{ success }}</p>
    {% if output_file %}
    <a href="/download/{{ output_file }}" class="download-link" download>下载压缩后的图片</a>
    {% endif %}
    {% endif %}
</div>
</body>
</html>

该HTML代码构建了一个简单的用户界面:

  1. 样式设置:通过CSS设置了页面的整体样式,包括背景颜色、容器样式、输入框、按钮等的样式。
  2. 表单部分:包含一个文件上传输入框,用于选择要压缩的图片;一个复选框,用于选择是否开启等比例缩放;一个文本输入框,用于输入目标分辨率;以及一个提交按钮。
  3. 提示信息展示:根据后端传递过来的变量,如 errorsuccessoutput_file,展示相应的错误信息、成功信息以及下载链接。

三、在1Panel上部署

(一)部署步骤

  1. 登录1Panel平台。
  2. 上传上述Python代码文件(假设命名为 app.py)和 templates/index.html文件到服务器指定目录。
  3. 在1Panel中创建一个新的Web应用,配置项目路径为代码所在目录。
  4. 设置应用的运行命令,例如 python app.py(确保服务器已安装Python及相关依赖库,如Flask、Pillow)。
  5. 配置端口等相关参数,确保应用能够正常访问。

(二)部署截图

image.png
image.png
直接访问 5000 端口即可
image.png