You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于PHP+Imagemagick的多图片处理表单改造需求

Upgrade Your PHP Image Processor to Handle Multiple Images, ZIPs, and Local Directories

Hey there! Since you're new to PHP, let's take your existing single-image uploader and turn it into a robust batch processor. We'll cover:

  • Multi-file uploads
  • Adding _T to processed filenames
  • ZIP archive support
  • Optional local directory processing

Let's dive in step by step.

1. Update the Form for Multi-File & ZIP Support

First, modify form.php to let users select multiple images, upload a ZIP, or optionally specify a local directory. We'll also update the session display to show all processed images.

<?php session_start(); ?>
<!DOCTYPE html>
<html>
<head>
<title>Batch Image Processor</title>
</head>
<body>
<?php 
// Display status messages
if (isset($_SESSION['message']) && $_SESSION['message']) {
    printf('<p><b>%s</b></p>', $_SESSION['message']);
    unset($_SESSION['message']);
}

// Display all processed images
if (isset($_SESSION['final_files']) && !empty($_SESSION['final_files'])) {
    echo '<h3>Processed Images:</h3>';
    foreach ($_SESSION['final_files'] as $file) {
        printf('<img src="%s" style="max-width: 200px; margin: 10px;" />', $file);
        echo '<br>';
    }
    unset($_SESSION['final_files']);
} 
?>

<form method="POST" action="process.php" enctype="multipart/form-data">
    <h4>Option 1: Upload Multiple Images</h4>
    <div>
        <span>Select images to process:</span>
        <input type="file" name="uploadedFiles[]" multiple accept="image/*" />
    </div>

    <h4>Option 2: Upload a ZIP of Images</h4>
    <div>
        <span>Upload ZIP archive:</span>
        <input type="file" name="uploadedZip" accept=".zip" />
    </div>

    <h4>Option 3: Process Local Directory</h4>
    <div>
        <span>Local directory path (e.g., ./local_images/):</span>
        <input type="text" name="localDir" placeholder="./local_images/" />
    </div>

    <br>
    <input type="submit" name="processBtn" value="Process Images" />
</form>
</body>
</html>

Key changes:

  • Added multiple to the file input and renamed it to uploadedFiles[] to accept multiple images
  • Added fields for ZIP upload and local directory input
  • Updated the session display to loop through all processed files

2. Rewrite process.php for Batch Processing

Next, update process.php to handle multiple files, ZIP archives, and local directories. We'll generate output filenames with _T appended instead of using fixed names.

<?php session_start();
require_once 'process-lib.php';
$imageProcessor = new ImageProcessor();
$message = '';
$processedFiles = [];

// Create upload directory if it doesn't exist
$uploadDir = './uploaded_files/';
if (!is_dir($uploadDir)) {
    mkdir($uploadDir, 0755, true);
}

// Handle multiple image uploads
if (isset($_POST['processBtn']) && isset($_FILES['uploadedFiles']) && $_FILES['uploadedFiles']['error'][0] !== UPLOAD_ERR_NO_FILE) {
    $files = $_FILES['uploadedFiles'];
    
    for ($i = 0; $i < count($files['name']); $i++) {
        if ($files['error'][$i] === UPLOAD_ERR_OK) {
            $fileTmpPath = $files['tmp_name'][$i];
            $fileName = $files['name'][$i];
            $fileExtension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
            $allowedExts = ['jpg', 'gif', 'png', 'jpeg'];

            if (in_array($fileExtension, $allowedExts)) {
                // Generate output filename: original_name_T.ext
                $baseName = pathinfo($fileName, PATHINFO_FILENAME);
                $outputFileName = $baseName . "_T." . $fileExtension;
                $destPath = $uploadDir . $fileName;
                $outputPath = $uploadDir . $outputFileName;

                if (move_uploaded_file($fileTmpPath, $destPath)) {
                    $imageProcessor->convert($destPath, $outputPath);
                    $processedFiles[] = $outputPath;
                } else {
                    $message .= "Error moving file: $fileName<br>";
                }
            } else {
                $message .= "Skipping non-image file: $fileName<br>";
            }
        }
    }
}

// Handle ZIP upload
if (isset($_POST['processBtn']) && isset($_FILES['uploadedZip']) && $_FILES['uploadedZip']['error'] === UPLOAD_ERR_OK) {
    $zipTmpPath = $_FILES['uploadedZip']['tmp_name'];
    $zip = new ZipArchive();
    
    if ($zip->open($zipTmpPath) === true) {
        $extractDir = $uploadDir . 'extracted_' . time() . '/';
        mkdir($extractDir);
        $zip->extractTo($extractDir);
        $zip->close();

        // Scan extracted directory for images
        $imageFiles = glob($extractDir . '*.[jJ][pP][gG]');
        $imageFiles = array_merge($imageFiles, glob($extractDir . '*.[pP][nN][gG]'));
        $imageFiles = array_merge($imageFiles, glob($extractDir . '*.[gG][iI][fF]'));

        foreach ($imageFiles as $imgPath) {
            $fileName = basename($imgPath);
            $baseName = pathinfo($fileName, PATHINFO_FILENAME);
            $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
            $outputPath = $uploadDir . $baseName . "_T." . $fileExtension;
            
            $imageProcessor->convert($imgPath, $outputPath);
            $processedFiles[] = $outputPath;
        }

        // Optional: Clean up extracted directory
        // rmdir($extractDir); // Uncomment if you want to delete after processing
    } else {
        $message .= "Failed to open ZIP file<br>";
    }
}

// Handle local directory processing
if (isset($_POST['processBtn']) && !empty($_POST['localDir'])) {
    $localDir = rtrim($_POST['localDir'], '/') . '/';
    if (is_dir($localDir) && is_readable($localDir)) {
        $imageFiles = glob($localDir . '*.[jJ][pP][gG]');
        $imageFiles = array_merge($imageFiles, glob($localDir . '*.[pP][nN][gG]'));
        $imageFiles = array_merge($imageFiles, glob($localDir . '*.[gG][iI][fF]'));

        foreach ($imageFiles as $imgPath) {
            $fileName = basename($imgPath);
            $baseName = pathinfo($fileName, PATHINFO_FILENAME);
            $fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
            $outputPath = $uploadDir . $baseName . "_T." . $fileExtension;
            
            $imageProcessor->convert($imgPath, $outputPath);
            $processedFiles[] = $outputPath;
        }
    } else {
        $message .= "Invalid or unreadable local directory<br>";
    }
}

// Set session messages and redirect
if (!empty($processedFiles)) {
    $message .= "Successfully processed " . count($processedFiles) . " images<br>";
    $_SESSION['final_files'] = $processedFiles;
}
$_SESSION['message'] = $message;
header("Location: form.php");
?>

Key changes:

  • Added loops to handle multiple uploaded files
  • Added ZIP archive extraction using ZipArchive (ensure PHP has this extension enabled)
  • Added local directory scanning with glob()
  • Generated dynamic output filenames with _T appended instead of fixed final.png
  • Collected all processed files into an array for display

3. Update ImageProcessor for Dynamic Output Paths

Modify process-lib.php to accept a custom output file path instead of using hardcoded values. We'll also remove the fixed final_file property since we're generating paths dynamically.

<?php
class ImageProcessor {
    private $upload_dir;

    public function __construct () {
        $this->upload_dir = 'uploaded_files';
        // Create directory if it doesn't exist
        if (!is_dir($this->upload_dir)) {
            mkdir($this->upload_dir, 0755, true);
        }
    }

    public function convert ($source_image, $output_file) {
        // Escape shell arguments to prevent security issues
        $sourceEscaped = escapeshellarg($source_image);
        $outputEscaped = escapeshellarg($output_file);

        // Your ImageMagick command, using dynamic output path
        $exec = "convert $sourceEscaped -resize '500x500>' -write mpr:img0 \
        -set option:distort:viewport '%[fx:max(w,h)]x%[fx:max(w,h)]' \
        -distort SRT '%[fx:(w>h)*(w/2)],%[fx:(h>w)*(h/2)] %[fx:max(w/h,h/w)] 0' \
        -fill white -colorize 70 mpr:img0 -gravity center -composite $outputEscaped";
        
        // Execute command and capture output/errors
        exec($exec, $output, $returnVar);
        
        // Log errors if command fails
        if ($returnVar !== 0) {
            $this->logger("Error processing $source_image: " . implode("\n", $output));
        }
    }

    public function logger ($message) {
        // Append timestamp to log entries
        $logMessage = date('Y-m-d H:i:s') . ": " . $message . "\n";
        file_put_contents('uploader.log', $logMessage, FILE_APPEND);
    }
}

Key changes:

  • Removed fixed file properties (main_file, final_file, etc.) since we use dynamic paths
  • Added escapeshellarg() to sanitize file paths (critical for security!)
  • Updated the convert method to accept an $output_file parameter
  • Improved logging with timestamps and error capture

Important Notes for Security & Functionality

  • Permissions: Make sure the uploaded_files directory is writable by your web server (chmod 0755 or 0775 usually works)
  • Shell Security: Always use escapeshellarg() when passing user-provided paths to shell commands to prevent command injection attacks
  • ZIP Extraction: The ZIP extraction creates a temporary directory—you might want to add cleanup logic to delete it after processing
  • Local Directory Access: Be careful with local directory input—restrict it to specific allowed directories if possible to prevent unauthorized file access
  • ImageMagick Path: If convert isn't found, use the full path to the executable (e.g., /usr/bin/convert) in your command

内容的提问来源于stack exchange,提问作者Ben Dodson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:41:00