本文目录导读:

这里为您提供一个完整的 PHP 后端处理 WebUploader 上传的解决方案,包含单文件、多文件上传以及分片上传的处理逻辑。
基础配置与公共函数
<?php
/**
* WebUploader PHP 后端处理类
*/
class UploadHandler {
private $config;
public function __construct($config = []) {
// 默认配置
$this->config = array_merge([
'upload_dir' => './uploads/', // 上传保存目录
'max_size' => 20 * 1024 * 1024, // 最大文件大小(20MB)
'allow_types' => ['jpg', 'jpeg', 'png', 'gif', 'zip', 'pdf'], // 允许的文件类型
'is_trim' => true, // 是否去除扩展名中的空格
], $config);
// 检查目录
if (!file_exists($this->config['upload_dir'])) {
@mkdir($this->config['upload_dir'], 0777, true);
}
}
/**
* 统一返回JSON格式
*/
private function jsonResponse($data, $status = true) {
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'success' => $status,
'data' => $data
]);
exit;
}
/**
* 获取文件扩展名
*/
private function getExtension($filename) {
$ext = pathinfo($filename, PATHINFO_EXTENSION);
return strtolower($ext);
}
/**
* 检查文件类型
*/
private function checkType($ext) {
if ($this->config['is_trim']) {
$ext = trim($ext);
}
return in_array($ext, $this->config['allow_types']);
}
/**
* 生成唯一文件名
*/
private function generateUniqueName($ext) {
$name = date('YmdHis') . '_' . uniqid() . '_' . rand(1000, 9999);
return $name . '.' . $ext;
}
/**
* 创建日期目录
*/
private function createDateDir() {
$year = date('Y');
$month = date('m');
$dir = $this->config['upload_dir'] . $year . '/' . $month . '/';
if (!file_exists($dir)) {
@mkdir($dir, 0777, true);
}
return $dir;
}
/**
* 处理上传的主方法
*/
public function handleUpload() {
$action = isset($_POST['action']) ? $_POST['action'] : 'upload';
switch ($action) {
case 'upload': // 普通上传
$result = $this->processUpload();
break;
case 'chunk': // 分片上传
$result = $this->processChunkUpload();
break;
default:
$this->jsonResponse(['msg' => '未知操作'], false);
}
$this->jsonResponse($result);
}
/**
* 普通文件上传
*/
private function processUpload() {
if (!isset($_FILES['file'])) {
return ['msg' => '没有文件上传'];
}
$file = $_FILES['file'];
// 检查错误码
if ($file['error'] !== UPLOAD_ERR_OK) {
$errorMsg = $this->uploadErrorMsg($file['error']);
return ['msg' => $errorMsg];
}
// 检查文件大小
if ($file['size'] > $this->config['max_size']) {
return ['msg' => '文件太大,最大支持 ' . ($this->config['max_size'] / 1024 / 1024) . 'MB'];
}
// 检查类型
$ext = $this->getExtension($file['name']);
if (!$this->checkType($ext)) {
return ['msg' => '不支持的文件类型: ' . $ext];
}
// 生成文件名和路径
$uploadDir = $this->createDateDir();
$fileName = $this->generateUniqueName($ext);
$filePath = $uploadDir . $fileName;
// 移动文件
if (!move_uploaded_file($file['tmp_name'], $filePath)) {
return ['msg' => '文件保存失败'];
}
// 返回文件信息
return [
'originalName' => $file['name'],
'fileName' => $fileName,
'filePath' => $filePath,
'fileSize' => $file['size'],
'fileType' => $ext,
'uploadTime' => date('Y-m-d H:i:s')
];
}
/**
* 分片上传处理
*/
private function processChunkUpload() {
// 分片信息
$chunk = isset($_POST['chunk']) ? intval($_POST['chunk']) : 0; // 当前第几分片
$chunks = isset($_POST['chunks']) ? intval($_POST['chunks']) : 1; // 总分片数
// 文件信息
$originalName = isset($_POST['name']) ? $_POST['name'] : 'unknown';
$file = isset($_FILES['file']) ? $_FILES['file'] : null;
if (!$file) {
return ['msg' => '没有文件数据'];
}
// 检查文件错误
if ($file['error'] !== UPLOAD_ERR_OK) {
return ['msg' => '分片上传失败'];
}
// 检查总大小(可选,需要前端提供)
$totalSize = isset($_POST['size']) ? intval($_POST['size']) : 0;
if ($totalSize > $this->config['max_size']) {
return ['msg' => '文件太大'];
}
// 临时分片保存目录
$tempDir = $this->config['upload_dir'] . 'temp/';
if (!file_exists($tempDir)) {
@mkdir($tempDir, 0777, true);
}
// 生成临时文件夹名(基于文件名和hash,这里简单处理)
$tempFolder = $tempDir . md5($originalName . $totalSize);
if (!file_exists($tempFolder)) {
@mkdir($tempFolder, 0777, true);
}
// 保存分片
$chunkFile = $tempFolder . '/' . $chunk;
if (!move_uploaded_file($file['tmp_name'], $chunkFile)) {
return ['msg' => '分片保存失败'];
}
// 检查是否所有分片都已上传
if ($this->isUploadComplete($tempFolder, $chunks)) {
// 合并分片
$result = $this->mergeChunks($tempFolder, $chunks, $originalName);
return $result;
}
return [
'chunk' => $chunk,
'chunks' => $chunks,
'msg' => '分片上传成功'
];
}
/**
* 检查分片是否全部上传完成
*/
private function isUploadComplete($tempFolder, $chunks) {
for ($i = 0; $i < $chunks; $i++) {
if (!file_exists($tempFolder . '/' . $i)) {
return false;
}
}
return true;
}
/**
* 合并分片
*/
private function mergeChunks($tempFolder, $chunks, $originalName) {
// 获取文件扩展名
$ext = $this->getExtension($originalName);
if (!$this->checkType($ext)) {
return ['msg' => '不支持的文件类型: ' . $ext];
}
// 创建最终上传目录
$uploadDir = $this->createDateDir();
$fileName = $this->generateUniqueName($ext);
$filePath = $uploadDir . $fileName;
// 写入文件
$file = fopen($filePath, 'wb');
if (!$file) {
return ['msg' => '无法创建最终文件'];
}
// 按顺序合并分片
for ($i = 0; $i < $chunks; $i++) {
$chunkFile = $tempFolder . '/' . $i;
if (file_exists($chunkFile)) {
$content = file_get_contents($chunkFile);
fwrite($file, $content);
@unlink($chunkFile); // 删除分片
}
}
fclose($file);
// 删除临时目录
@rmdir($tempFolder);
// 获取文件大小
$fileSize = filesize($filePath);
return [
'originalName' => $originalName,
'fileName' => $fileName,
'filePath' => $filePath,
'fileSize' => $fileSize,
'fileType' => $ext,
'uploadTime' => date('Y-m-d H:i:s'),
'msg' => '上传成功'
];
}
/**
* 获取上传错误信息
*/
private function uploadErrorMsg($errorCode) {
$messages = [
UPLOAD_ERR_INI_SIZE => '文件大小超过服务器限制',
UPLOAD_ERR_FORM_SIZE => '文件大小超过表单限制',
UPLOAD_ERR_PARTIAL => '文件只有部分被上传',
UPLOAD_ERR_NO_FILE => '没有文件被上传',
UPLOAD_ERR_NO_TMP_DIR => '找不到临时文件夹',
UPLOAD_ERR_CANT_WRITE => '文件写入失败',
UPLOAD_ERR_EXTENSION => '文件上传被扩展阻止',
];
return isset($messages[$errorCode]) ? $messages[$errorCode] : '未知错误';
}
}
入口文件 upload.php
<?php
/**
* WebUploader 上传入口文件
* 使用方法: 引入此文件即可
*/
// 设置时区
date_default_timezone_set('Asia/Shanghai');
// 配置
$config = [
'upload_dir' => __DIR__ . '/uploads/', // 上传目录
'max_size' => 100 * 1024 * 1024, // 最大100MB
'allow_types' => ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'zip', 'rar', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'mp4', 'mp3'],
];
// 实例化并处理
$handler = new UploadHandler($config);
$handler->handleUpload();
?>
前端示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">WebUploader 文件上传</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/webuploader/0.1.5/webuploader.min.css">
<style>
.uploader-list {
margin: 20px 0;
}
.file-item {
padding: 10px;
border: 1px solid #ddd;
margin: 5px 0;
background: #f9f9f9;
}
.progress {
height: 10px;
background: #e0e0e0;
margin-top: 5px;
}
.progress-bar {
height: 100%;
background: #4CAF50;
}
#picker {
padding: 10px 20px;
background: #2196F3;
color: white;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<div id="uploader">
<div id="picker">选择文件</div>
<div class="uploader-list" id="fileList"></div>
<button type="button" class="btn btn-start">开始上传</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webuploader/0.1.5/webuploader.min.js"></script>
<script>
$(function() {
var uploader = WebUploader.create({
// 上传地址
server: 'upload.php',
// 使用分片上传
chunked: true,
chunkSize: 2 * 1024 * 1024, // 每片2MB
// 并发数
threads: 3,
// 文件类型
accept: {
title: 'Images',
extensions: 'jpg,jpeg,png,gif',
mimeTypes: 'image/jpeg,image/png,image/gif'
},
// 单个文件大小限制
fileSizeLimit: 100 * 1024 * 1024,
fileSingleSizeLimit: 50 * 1024 * 1024,
// 选择文件按钮
pick: '#picker'
});
// 添加到上传队列
uploader.on('fileQueued', function(file) {
var html = '<div class="file-item" id="' + file.id + '">' +
'<span class="file-name">' + file.name + '</span>' +
'<span class="file-size">' + Math.floor(file.size / 1024 / 1024) + 'MB</span>' +
'<div class="progress"><div class="progress-bar" style="width:0%"></div></div>' +
'<span class="file-status"></span>' +
'</div>';
$('#fileList').append(html);
});
// 上传进度
uploader.on('uploadProgress', function(file, percentage) {
var $li = $('#' + file.id);
$li.find('.progress-bar').css('width', percentage * 100 + '%');
});
// 上传成功
uploader.on('uploadSuccess', function(file, response) {
var $li = $('#' + file.id);
$li.find('.file-status').text('上传成功: ' + response.data.filePath);
});
// 上传失败
uploader.on('uploadError', function(file, reason) {
var $li = $('#' + file.id);
$li.find('.file-status').text('上传失败: ' + reason);
});
// 全部上传完成
uploader.on('uploadFinished', function() {
alert('所有文件上传完成');
});
// 开始上传按钮
$('.btn-start').on('click', function() {
uploader.upload();
});
});
</script>
</body>
</html>
高级功能扩展
<?php
/**
* 扩展功能:包括图片压缩、下载、进度查询等
*/
class AdvancedUploadHandler extends UploadHandler {
/**
* 图片压缩处理
*/
public function compressImage($sourcePath, $targetPath, $maxWidth = 1000) {
// 获取图片信息
list($width, $height, $type) = getimagesize($sourcePath);
// 如果图片宽度小于最大宽度,不进行压缩
if ($width <= $maxWidth) {
copy($sourcePath, $targetPath);
return true;
}
// 计算压缩后尺寸
$ratio = $maxWidth / $width;
$newWidth = $maxWidth;
$newHeight = $height * $ratio;
// 创建画布
$thumb = imagecreatetruecolor($newWidth, $newHeight);
// 根据类型加载源图
switch ($type) {
case IMAGETYPE_JPEG:
$source = imagecreatefromjpeg($sourcePath);
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagejpeg($thumb, $targetPath, 80);
break;
case IMAGETYPE_PNG:
$source = imagecreatefrompng($sourcePath);
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagepng($thumb, $targetPath, 6);
break;
default:
return false;
}
imagedestroy($thumb);
imagedestroy($source);
return true;
}
/**
* 异步下载大文件
*/
public function downloadFile($filePath, $downloadName = '') {
if (!file_exists($filePath)) {
http_response_code(404);
exit('File not found');
}
if (empty($downloadName)) {
$downloadName = basename($filePath);
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $downloadName . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filePath));
readfile($filePath);
exit;
}
/**
* 获取上传进度(需要配合前端使用)
*/
public function getProgress($tempDir) {
$files = glob($tempDir . '/*');
if ($files) {
return count($files);
}
return 0;
}
}
?>
注意事项
1 安全配置
- 设置 Web 服务器上传大小限制(PHP.ini)
- 验证文件类型(不仅靠扩展名,还要检查 MIME)
- 使用安全的文件命名方式
- 控制上传目录的访问权限
2 PHP 配置建议
; php.ini 配置 upload_max_filesize = 100M post_max_size = 100M max_execution_time = 300 memory_limit = 128M
3 前端注意事项
- 合理设置分片大小(2MB-5MB为宜)
- 设置并发数(2-3个)
- 添加超时处理
- 实现断点续传逻辑
这个方案完整支持了 WebUploader 的普通上传和分片上传功能,可以根据实际需求调整配置和扩展功能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播