首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 接收二進制原始數據並保存為圖片

     編輯:PHP 相關知識

處理 HTTP 原始 POST 體(php://input)、WebSocket 幂、或客戶端直接發送二進制圖片流時,需繞過 $_FILES 直接讀取 $GLOBALS['HTTP_RAW_POST_DATA'](PHP 5.6-)或 file_get_contents('php://input')(通用)。本文提供完整接收、驗證、保存流程。

核心代碼

<?php
// 接收端:save_raw_image.php

// 1. 配置
$saveDir = __DIR__ . '/uploads/';
$maxSize = 5 * 1024 * 1024; // 5MB
$allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];

if (!is_dir($saveDir)) {
    mkdir($saveDir, 0755, true);
}

// 2. 獲取原始二進制數據
$raw = $GLOBALS['HTTP_RAW_POST_DATA'] ?? file_get_contents('php://input');
if (empty($raw)) {
    http_response_code(400);
    exit('Empty body');
}

// 3. 大小檢查
if (strlen($raw) > $maxSize) {
    http_response_code(413);
    exit('File too large');
}

// 4. 類型檢測(finfo 更可靠)
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->buffer($raw);
if (!in_array($mime, $allowedTypes, true)) {
    http_response_code(415);
    exit("Unsupported type: $mime");
}

// 5. 生成安全文件名
$ext = [
    'image/jpeg' => 'jpg',
    'image/png'  => 'png',
    'image/gif'  => 'gif',
    'image/webp' => 'webp',
][$mime];
$filename = bin2hex(random_bytes(8)) . '.' . $ext; // 防衝突、無特殊字符
$filepath = $saveDir . $filename;

// 6. 原子寫入(臨時文件 + rename)
$tmpFile = $filepath . '.tmp.' . random_int(1000, 9999);
$bytes = file_put_contents($tmpFile, $raw, LOCK_EX);
if ($bytes === false || $bytes !== strlen($raw)) {
    @unlink($tmpFile);
    http_response_code(500);
    exit('Write failed');
}
rename($tmpFile, $filepath); // 原子操作,防止部分寫入被讀取

// 7. 返回結果
header('Content-Type: application/json');
echo json_encode([
    'success' => true,
    'filename' => $filename,
    'path' => $filepath,
    'size' => $bytes,
    'mime' => $mime,
]);
?>

客戶端發送示例

cURL 命令列

curl -X POST \
  -H "Content-Type: image/png" \
  --data-binary @photo.png \
  https://example.com/save_raw_image.php

JavaScript Fetch

const fileInput = document.querySelector('input[type=file]');
const file = fileInput.files[0];

fetch('/save_raw_image.php', {
    method: 'POST',
    headers: {'Content-Type': file.type},
    body: file // 直接發送 Blob/File,不經 FormData
}).then(r => r.json()).then(console.log);

Python Requests

import requests
with open('photo.jpg', 'rb') as f:
    r = requests.post('https://example.com/save_raw_image.php', 
                      data=f, 
                      headers={'Content-Type': 'image/jpeg'})
print(r.json())

關鍵點總結

環節最佳實踐
讀取輸入file_get_contents('php://input') 通用、不受 always_populate_raw_post_data 影響
類型驗證finfo::buffer() 基於魔數檢測,不可信任 Client 傳來的 Content-Type
文件名隨機哈希 + 正確副檔名,避免覆蓋、注入、編碼問題
寫入安全臨時文件 + rename() 原子替換,防止併發讀到半寫文件
權限控制上傳目錄設 open_basedir、禁用腳本執行(Nginx location ~ \.php$ {deny all;})
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved