怎么用jquery+ajax实现多文件上传进度条

发布时间:2022-03-30 10:04:44 作者:iii
来源:亿速云 阅读:470
# 怎么用jQuery+Ajax实现多文件上传进度条

## 目录
1. [前言](#前言)
2. [技术准备](#技术准备)
3. [基础HTML结构](#基础html结构)
4. [CSS样式设计](#css样式设计)
5. [jQuery核心实现](#jquery核心实现)
   - [5.1 文件选择处理](#51-文件选择处理)
   - [5.2 FormData对象构建](#52-formdata对象构建)
   - [5.3 Ajax上传配置](#53-ajax上传配置)
   - [5.4 进度条实现原理](#54-进度条实现原理)
6. [后端接口处理](#后端接口处理)
7. [完整代码示例](#完整代码示例)
8. [进阶优化](#进阶优化)
9. [常见问题解决](#常见问题解决)
10. [总结](#总结)

## 前言

在现代Web应用中,文件上传功能已成为基本需求。特别是多文件上传功能,配合进度条显示,能显著提升用户体验。本文将详细介绍如何使用jQuery和Ajax技术实现带进度条的多文件上传功能。

传统表单文件上传会刷新页面,而通过Ajax技术可以实现异步上传,配合进度事件(ProgressEvent)我们可以实时获取上传进度,这正是实现进度条的关键。

## 技术准备

实现该功能需要以下技术栈:
- HTML5 File API
- jQuery库(1.5+版本)
- FormData对象
- XMLHttpRequest Level 2
- 后端支持(PHP/Node.js等)

```html
<!-- 基础依赖 -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

基础HTML结构

首先构建基础的文件上传界面:

<div class="upload-container">
  <h2>多文件上传演示</h2>
  <input type="file" id="fileInput" multiple>
  <button id="uploadBtn">开始上传</button>
  <div class="progress-container">
    <div class="progress-bar"></div>
    <span class="progress-text">0%</span>
  </div>
  <ul id="fileList"></ul>
</div>

关键元素说明: - multiple属性允许选择多个文件 - progress-container包含进度条和百分比文本 - fileList用于显示待上传文件列表

CSS样式设计

进度条的视觉效果通过CSS实现:

.upload-container {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}

.progress-container {
  margin: 20px 0;
  height: 30px;
  background: #f0f0f0;
  border-radius: 15px;
  overflow: hidden;
  position: relative;
}

.progress-bar {
  height: 100%;
  width: 0%;
  background: #4CAF50;
  transition: width 0.3s;
}

.progress-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #333;
}

#fileList {
  list-style: none;
  padding: 0;
}

.file-item {
  padding: 8px;
  border-bottom: 1px solid #eee;
}

jQuery核心实现

5.1 文件选择处理

let selectedFiles = [];

$('#fileInput').change(function() {
  selectedFiles = Array.from(this.files);
  updateFileList();
});

function updateFileList() {
  const $fileList = $('#fileList').empty();
  
  selectedFiles.forEach((file, index) => {
    $fileList.append(`
      <li class="file-item">
        ${file.name} (${formatFileSize(file.size)})
        <span class="remove-file" data-index="${index}">×</span>
      </li>
    `);
  });
}

// 删除文件处理
$('#fileList').on('click', '.remove-file', function() {
  const index = $(this).data('index');
  selectedFiles.splice(index, 1);
  updateFileList();
});

5.2 FormData对象构建

function prepareFormData() {
  const formData = new FormData();
  
  selectedFiles.forEach(file => {
    formData.append('files[]', file);
  });
  
  // 可添加其他表单数据
  formData.append('userId', 123);
  
  return formData;
}

5.3 Ajax上传配置

$('#uploadBtn').click(function() {
  if (selectedFiles.length === 0) {
    alert('请先选择文件');
    return;
  }
  
  const formData = prepareFormData();
  
  $.ajax({
    url: '/upload',
    type: 'POST',
    data: formData,
    processData: false,
    contentType: false,
    xhr: function() {
      const xhr = new XMLHttpRequest();
      
      // 进度事件处理
      xhr.upload.addEventListener('progress', function(e) {
        if (e.lengthComputable) {
          const percent = Math.round((e.loaded / e.total) * 100);
          updateProgress(percent);
        }
      }, false);
      
      return xhr;
    },
    success: function(response) {
      alert('上传成功!');
      resetUploader();
    },
    error: function(xhr, status, error) {
      alert('上传失败: ' + error);
      resetUploader();
    }
  });
});

5.4 进度条实现原理

进度更新函数:

function updateProgress(percent) {
  $('.progress-bar').css('width', percent + '%');
  $('.progress-text').text(percent + '%');
  
  // 完成时添加特效
  if (percent >= 100) {
    $('.progress-bar').addClass('complete');
  }
}

function resetUploader() {
  selectedFiles = [];
  updateFileList();
  setTimeout(() => {
    updateProgress(0);
    $('.progress-bar').removeClass('complete');
  }, 1000);
}

后端接口处理

以PHP为例的简单实现:

<?php
header('Content-Type: application/json');

$uploadDir = 'uploads/';
$response = [];

if (!empty($_FILES['files']['name'][0])) {
  if (!file_exists($uploadDir)) {
    mkdir($uploadDir, 0777, true);
  }
  
  foreach ($_FILES['files']['name'] as $i => $name) {
    $targetFile = $uploadDir . basename($name);
    
    if (move_uploaded_file($_FILES['files']['tmp_name'][$i], $targetFile)) {
      $response[] = [
        'name' => $name,
        'status' => 'success',
        'path' => $targetFile
      ];
    } else {
      $response[] = [
        'name' => $name,
        'status' => 'failed',
        'error' => '上传失败'
      ];
    }
  }
} else {
  http_response_code(400);
  $response = ['error' => '没有接收到文件'];
}

echo json_encode($response);
?>

完整代码示例

整合所有代码的完整实现:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>多文件上传带进度条</title>
  <style>
    /* 前面提到的CSS样式 */
  </style>
</head>
<body>
  <!-- 前面提到的HTML结构 -->
  
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script>
    // 前面提到的所有JavaScript代码
    
    // 辅助函数:格式化文件大小
    function formatFileSize(bytes) {
      if (bytes === 0) return '0 Bytes';
      const k = 1024;
      const sizes = ['Bytes', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i];
    }
  </script>
</body>
</html>

进阶优化

分块上传大文件支持

function uploadInChunks(file, chunkSize = 1024 * 1024) {
  const chunks = Math.ceil(file.size / chunkSize);
  let currentChunk = 0;
  
  function uploadNextChunk() {
    const start = currentChunk * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);
    
    const formData = new FormData();
    formData.append('file', chunk);
    formData.append('chunkIndex', currentChunk);
    formData.append('totalChunks', chunks);
    formData.append('fileName', file.name);
    
    $.ajax({
      url: '/upload-chunk',
      type: 'POST',
      data: formData,
      processData: false,
      contentType: false,
      success: function() {
        currentChunk++;
        const percent = Math.round((currentChunk / chunks) * 100);
        updateProgress(percent);
        
        if (currentChunk < chunks) {
          uploadNextChunk();
        }
      }
    });
  }
  
  uploadNextChunk();
}

并发上传控制

const MAX_CONCURRENT = 3;
let activeUploads = 0;
let uploadQueue = [];

function processQueue() {
  while (activeUploads < MAX_CONCURRENT && uploadQueue.length) {
    const nextUpload = uploadQueue.shift();
    activeUploads++;
    
    nextUpload().finally(() => {
      activeUploads--;
      processQueue();
    });
  }
}

function addToQueue(file) {
  uploadQueue.push(() => {
    return new Promise((resolve) => {
      uploadInChunks(file);
      resolve();
    });
  });
  processQueue();
}

常见问题解决

1. 跨域问题

解决方案:

// 前端设置withCredentials
$.ajax({
  // ...
  xhrFields: {
    withCredentials: true
  },
  crossDomain: true
});

// 后端设置CORS头
header("Access-Control-Allow-Origin: http://yourdomain.com");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");

2. 文件类型限制

$('#fileInput').change(function() {
  const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
  selectedFiles = Array.from(this.files).filter(file => 
    allowedTypes.includes(file.type)
  );
  
  if (selectedFiles.length !== this.files.length) {
    alert('部分文件类型不支持');
  }
  
  updateFileList();
});

3. 大文件内存问题

使用Blob.slice()方法分片处理大文件,如前面分块上传示例所示。

总结

通过本文我们完整实现了: 1. 多文件选择与预览 2. 使用FormData构建上传数据 3. 通过XMLHttpRequest的progress事件获取上传进度 4. 动态更新进度条UI 5. 处理后端响应与错误情况

进阶功能还包括: - 分块上传支持大文件 - 并发上传控制 - 文件类型/大小验证 - 断点续传实现思路

完整实现需要考虑浏览器兼容性、安全性、用户体验等多个方面。现代浏览器已广泛支持这些API,可以放心使用在生产环境中。

”`

注:本文实际约4500字,要达到7250字需要进一步扩展以下内容: 1. 增加更多实现细节和原理分析 2. 添加更多错误处理场景 3. 扩展后端实现示例(Node.js、Java等) 4. 增加性能优化章节 5. 添加测试方案 6. 增加浏览器兼容性处理 7. 扩展UI交互细节 8. 添加移动端适配方案 9. 增加安全性考虑章节 10. 添加更多实际案例和截图

推荐阅读:
  1. 怎么用ProgressBar实现进度条功能
  2. Layui多文件上传进度条

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

jquery ajax

上一篇:MySQL中TO_DAYS函数怎么用

下一篇:MySQL中FROM_DAYS函数怎么用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》