PHP 怎么测试文件上传

wen PHP项目 2

本文目录导读:

PHP 怎么测试文件上传

  1. 使用 PHP 内置测试类(推荐)
  2. 使用 curl 命令测试
  3. 编写独立的测试脚本
  4. 使用 BrowserStack / TestingBot 云测试
  5. 完整的测试脚本示例
  6. Postman 测试
  7. 最佳实践建议

在 PHP 中测试文件上传有多种方法,以下是几种常见且实用的测试方案:

使用 PHP 内置测试类(推荐)

使用 PHPUnitvfsStream

<?php
use PHPUnit\Framework\TestCase;
use org\bovigo\vfs\vfsStream;
class FileUploadTest extends TestCase
{
    public function testFileUpload()
    {
        // 创建虚拟文件系统
        $root = vfsStream::setup('uploads');
        // 模拟上传文件
        $file = [
            'name' => 'test.txt',
            'type' => 'text/plain',
            'tmp_name' => vfsStream::newFile('test.txt')
                ->withContent('这是一段测试内容')
                ->at($root)
                ->url(),
            'error' => UPLOAD_ERR_OK,
            'size' => 57
        ];
        // 调用上传处理函数
        $result = handleFileUpload($file, vfsStream::url('uploads') . '/');
        // 断言
        $this->assertTrue($result['success']);
        $this->assertFileExists(vfsStream::url('uploads') . '/test.txt');
    }
    // 测试上传错误
    public function testFileUploadWithError()
    {
        $file = [
            'name' => 'test.txt',
            'type' => 'text/plain',
            'tmp_name' => '',
            'error' => UPLOAD_ERR_NO_FILE,
            'size' => 0
        ];
        $result = handleFileUpload($file, '/tmp/uploads/');
        $this->assertFalse($result['success']);
        $this->assertEquals('没有文件上传', $result['message']);
    }
}

使用 curl 命令测试

创建测试脚本 upload_test.php

<?php
function handleFileUpload($file, $uploadDir) {
    $uploadDir = rtrim($uploadDir, '/') . '/';
    if ($file['error'] !== UPLOAD_ERR_OK) {
        return ['success' => false, 'message' => '上传失败,错误码: ' . $file['error']];
    }
    if (!is_uploaded_file($file['tmp_name'])) {
        return ['success' => false, 'message' => '不是一个有效的上传文件'];
    }
    // 验证文件类型和大小
    if ($file['size'] > 2 * 1024 * 1024) {
        return ['success' => false, 'message' => '文件太大'];
    }
    // 移动文件
    $targetPath = $uploadDir . time() . '_' . basename($file['name']);
    if (move_uploaded_file($file['tmp_name'], $targetPath)) {
        return ['success' => true, 'path' => $targetPath, 'message' => '上传成功'];
    }
    return ['success' => false, 'message' => '文件保存失败'];
}
// 处理上传请求
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
    header('Content-Type: application/json');
    echo json_encode(handleFileUpload($_FILES['file'], '/tmp/uploads/'));
}

使用 curl 测试

# 测试文件上传
curl -X POST -F "file=@/path/to/local/file.txt" http://localhost/upload_test.php
# 测试图片上传
curl -X POST -F "image=@/path/to/image.png;type=image/png" http://localhost/upload_test.php
# 测试文件上传并设置 MIME 类型
curl -X POST -F "file=@/path/to/document.pdf;type=application/pdf" http://localhost/upload_test.php
# 测试多个文件
curl -X POST -F "files[]=@/path/to/file1.txt" -F "files[]=@/path/to/file2.txt" http://localhost/upload_test.php

编写独立的测试脚本

创建 test_upload.php

<?php
// 创建测试方法
function createTestFile($filename, $content) {
    $tempDir = sys_get_temp_dir();
    $tempFile = $tempDir . '/' . $filename;
    file_put_contents($tempFile, $content);
    return $tempFile;
}
function simulateFileUpload() {
    // 模拟表单上传
    $_FILES = [
        'file' => [
            'name' => 'test.txt',
            'type' => 'text/plain',
            'tmp_name' => createTestFile('phptmp', '这是模拟的上传文件内容'),
            'error' => UPLOAD_ERR_OK,
            'size' => 57
        ]
    ];
    // 创建临时上传目录
    $uploadDir = sys_get_temp_dir() . '/uploads';
    if (!is_dir($uploadDir)) {
        mkdir($uploadDir, 0777, true);
    }
    // 调用上传处理逻辑
    $result = processUpload($uploadDir);
    // 验证结果
    echo "测试结果:" . json_encode($result) . "\n";
    // 清理
    unlink($_FILES['file']['tmp_name']);
    return $result;
}
function processUpload($uploadDir) {
    if (!isset($_FILES['file'])) {
        return ['success' => false, 'message' => '没有找到文件'];
    }
    $file = $_FILES['file'];
    if ($file['error'] !== UPLOAD_ERR_OK) {
        return ['success' => false, 'message' => '上传错误'];
    }
    $targetFile = rtrim($uploadDir, '/') . '/' . $file['name'];
    if (move_uploaded_file($file['tmp_name'], $targetFile)) {
        return ['success' => true, 'path' => $targetFile];
    }
    return ['success' => false, 'message' => '移动失败'];
}
// 执行测试
simulateFileUpload();

使用 BrowserStack / TestingBot 云测试

<?php
require 'vendor/autoload.php';
class BrowserUploadTest extends PHPUnit_Extensions_Selenium2TestCase
{
    public function setUp() {
        $this->setBrowser('firefox');
        $this->setBrowserUrl('http://localhost:3000/');
        // 云测试平台配置
        $this->setHost('hub-cloud.browserstack.com');
        $this->setPort(80);
        $this->setBrowserUrl('http://localhost');
    }
    public function testFileUpload() {
        $this->open('/upload_form.php');
        // 找到文件上传输入框
        $fileInput = $this->byCssSelector('input[type="file"]');
        // 设置文件路径
        $fileInput->value(__DIR__ . '/test_files/upload_test.txt');
        // 提交表单
        $this->byId('submit')->click();
        // 验证上传结果
        $this->assertContains('上传成功', $this->body()->text());
    }
}

完整的测试脚本示例

<?php
class FileUploadTester {
    private $uploadDir;
    private $testResults = [];
    public function __construct($uploadDir) {
        $this->uploadDir = $uploadDir;
    }
    public function testAll() {
        $this->testTextFileUpload();
        $this->testImageFileUpload();
        $this->testLargeFile();
        $this->testEmptyFile();
        $this->testInvalidFileType();
        return $this->testResults;
    }
    private function testTextFileUpload() {
        $file = $this->createMockFile('test.txt', 'text/plain', 'Hello World');
        $result = $this->uploadFile($file);
        $this->testResults['text_upload'] = $result;
    }
    private function testImageFileUpload() {
        // 创建模拟图片文件
        $imageContent = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ');
        $file = $this->createMockFile('test.png', 'image/png', $imageContent);
        $result = $this->uploadFile($file);
        $this->testResults['image_upload'] = $result;
    }
    private function createMockFile($name, $type, $content) {
        $tempFile = tempnam(sys_get_temp_dir(), 'upload');
        file_put_contents($tempFile, $content);
        return [
            'name' => $name,
            'type' => $type,
            'tmp_name' => $tempFile,
            'error' => UPLOAD_ERR_OK,
            'size' => strlen($content)
        ];
    }
    private function uploadFile($file) {
        // 这里实现实际的上传逻辑
        $targetFile = rtrim($this->uploadDir, '/') . '/' . time() . '_' . $file['name'];
        if (move_uploaded_file($file['tmp_name'], $targetFile)) {
            unlink($file['tmp_name']);
            return ['success' => true, 'message' => '文件上传成功'];
        }
        return ['success' => false, 'message' => '文件上传失败'];
    }
}
// 使用测试器
$tester = new FileUploadTester('/tmp/uploads/');
$results = $tester->testAll();
echo "测试结果:\n";
foreach ($results as $test => $result) {
    echo $test . ': ' . ($result['success'] ? '✓' : '✗') . ' ' . $result['message'] . "\n";
}

Postman 测试

使用 Postman 进行测试:

  1. 创建新请求
  2. 选择 POST 方法
  3. 在 Body 中选择 form-data
  4. 添加 key 为 file 的文件字段
  5. 选择要上传的文件
  6. 发送请求并查看响应

最佳实践建议

  1. 使用 is_uploaded_file() 验证:确保文件确实是 HTTP POST 上传的
  2. 验证文件类型和大小:使用 $_FILES['file']['size'] 和 content type 验证
  3. 使用安全的文件名:不要直接使用用户提供的文件名
  4. 设置临时目录:确保 php.ini 中的 upload_tmp_dir 可写
  5. 错误处理:始终检查 $_FILES['file']['error'] 的值

这些方法覆盖了单元测试、集成测试和手动测试的不同场景,可以根据具体需求选择使用。

抱歉,评论功能暂时关闭!