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

PHP 結合 Ajax 實現非同步檔案上傳(HTML5 FileReader)

     編輯:PHP 綜合知識

核心流程

  1. 取得 File 物件(<input type="file"> 或拖曳事件)
  2. 使用 FileReader 讀取檔案(二進位、Base64、文字)
  3. 透過 XMLHttpRequest 或 fetch 送出

關鍵技術點

  • Firefox:支援 xhr.sendAsBinary() 直接送二進位
  • Chrome/其他:無 sendAsBinary,需用 FormData 或 Base64 字串
  • 跨瀏覽器相容:建議統一使用 FormData + xhr.send(formData)

完整範例:拖曳上傳 + FileReader 預覽

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5 FileReader 檔案上傳預覽</title>
<style>
.drop-zone { border:2px dashed #ccc; padding:20px; text-align:center; }
.drop-zone.dragover { border-color:#007bff; background:#e7f1ff; }
.preview img { max-width:200px; margin:10px; }
</style>
</head>
<body>
<div class="drop-zone" id="dropZone">拖曳圖片到此處上傳</div>
<div class="preview" id="preview"></div>

<script>
const dropZone = document.getElementById('dropZone');
const preview = document.getElementById('preview');

['dragenter','dragover'].forEach(evt => 
    dropZone.addEventListener(evt, e => { e.preventDefault(); e.stopPropagation(); dropZone.classList.add('dragover'); })
);
['dragleave','drop'].forEach(evt => 
    dropZone.addEventListener(evt, e => { e.preventDefault(); e.stopPropagation(); dropZone.classList.remove('dragover'); })
);

dropZone.addEventListener('drop', e => {
    const files = e.dataTransfer.files;
    handleFiles(files);
});

function handleFiles(files) {
    for (const file of files) {
        if (!file.type.startsWith('image/')) continue;
        const reader = new FileReader();
        reader.onload = ev => {
            const img = document.createElement('img');
            img.src = ev.target.result; // Base64 Data URL
            preview.appendChild(img);
            uploadFile(file); // 實際上傳
        };
        reader.readAsDataURL(file);
    }
}

function uploadFile(file) {
    const formData = new FormData();
    formData.append('file', file);

    fetch('upload.php', { method: 'POST', body: formData })
        .then(r => r.json())
        .then(res => console.log('上傳結果:', res))
        .catch(err => console.error('上傳失敗:', err));
}
</script>
</body>
</html>

FileReader 常用方法

方法結果格式適用場景
readAsDataURL(file)Base64 Data URL圖片預覽、直接嵌入 src
readAsBinaryString(file)二進位字串舊版相容、需手動組 multipart
readAsText(file, encoding)文字字串CSV、JSON、日誌檔讀取
readAsArrayBuffer(file)ArrayBuffer二進位運算、WebAssembly、大檔分片

進階:大檔分片上傳(斷點續傳)

async function uploadChunked(file, chunkSize = 1024 * 1024) { // 1MB 分片
    const totalChunks = Math.ceil(file.size / chunkSize);
    for (let i = 0; i < totalChunks; i++) {
        const start = i * chunkSize;
        const chunk = file.slice(start, start + chunkSize);
        const formData = new FormData();
        formData.append('chunk', chunk);
        formData.append('index', i);
        formData.append('total', totalChunks);
        formData.append('filename', file.name);

        await fetch('upload_chunk.php', { method: 'POST', body: formData });
        console.log(`進度: ${Math.round((i+1)/totalChunks*100)}%`);
    }
}

伺服器端接收(upload.php)

<?php
$targetDir = 'uploads/';
$fileName = basename($_FILES['file']['name']);
$targetFile = $targetDir . uniqid() . '_' . $fileName;

if (move_uploaded_file($_FILES['file']['tmp_name'], $targetFile)) {
    echo json_encode(['success' => true, 'path' => $targetFile]);
} else {
    http_response_code(500);
    echo json_encode(['success' => false, 'error' => '移動檔案失敗']);
}
?>

總結

  • 現代瀏覽器請直接用 FormData + fetch/XMLHttpRequest
  • FileReader 適合**預覽**、**客戶端處理**(壓縮、轉檔、驗證)
  • 大檔案建議分片上傳,支援斷點續傳與進度顯示
  • 伺服器端務必驗證檔案類型、大小、副檔名,防止惡意上傳
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved