返回

巧用 HTML5 File API 实现前端大文件上传,分段断点续传,轻松搞定!

前端

前言

在当今互联网时代,我们经常需要上传大文件,比如视频、音频、图片等。传统的文件上传方式往往存在速度慢、容易中断等问题,为了解决这些问题,HTML5 File API 应运而生。HTML5 File API 提供了一系列强大的功能,可以帮助我们轻松实现大文件上传,同时支持断点续传,极大地提高了文件上传的效率和稳定性。

原理简介

HTML5 File API 允许我们通过 JavaScript 直接访问和操作文件,包括读取文件内容、获取文件元数据等。其中,FileReader 对象可以将文件读取为二进制数据,然后我们可以使用 XMLHttpRequest 对象将二进制数据分块发送到服务器。如果上传过程因网络中断而失败,我们可以通过断点续传功能继续上传剩余部分,而无需重新上传整个文件。

实现步骤

1. HTML 标记

首先,我们需要在 HTML 页面中添加一个文件选择控件,以便用户选择要上传的文件。可以使用 <input> 元素的 type 属性设置为 file 来实现。

<input type="file" id="file-input">

2. JavaScript 代码

接下来,我们需要编写 JavaScript 代码来处理文件上传逻辑。首先,我们需要使用 document.querySelector() 方法获取文件选择控件的引用。然后,可以使用 addEventListener() 方法为文件选择控件添加一个 change 事件监听器,以便在用户选择文件后触发该事件。在事件处理函数中,我们可以使用 FileReader 对象读取文件内容,并使用 XMLHttpRequest 对象将二进制数据分块发送到服务器。

const fileInput = document.querySelector('#file-input');

fileInput.addEventListener('change', (e) => {
  const file = e.target.files[0];

  const reader = new FileReader();
  reader.onload = () => {
    const binaryData = reader.result;

    const xhr = new XMLHttpRequest();
    xhr.open('POST', 'upload.php');
    xhr.setRequestHeader('Content-Type', 'application/octet-stream');

    const chunkSize = 1024 * 1024; // 1MB
    const totalChunks = Math.ceil(binaryData.length / chunkSize);
    let currentChunk = 0;

    const sendChunk = () => {
      const startByte = currentChunk * chunkSize;
      const endByte = Math.min(startByte + chunkSize, binaryData.length);
      const chunk = binaryData.slice(startByte, endByte);

      xhr.send(chunk);

      currentChunk++;

      if (currentChunk < totalChunks) {
        setTimeout(sendChunk, 100); // 模拟网络延迟
      }
    };

    sendChunk();
  };

  reader.readAsBinaryString(file);
});

3. 服务器端处理

在服务器端,我们需要编写代码来接收和处理上传的文件数据。我们可以使用 PHP、Java、Python 等语言来实现。这里以 PHP 为例,服务器端代码如下:

<?php
$tempFile = $_FILES['file']['tmp_name'];
$fileName = $_FILES['file']['name'];
$fileSize = $_FILES['file']['size'];

$handle = fopen($tempFile, 'rb');
$chunkSize = 1024 * 1024; // 1MB
$totalChunks = ceil($fileSize / $chunkSize);
$currentChunk = 0;

while ($currentChunk < $totalChunks) {
  $chunk = fread($handle, $chunkSize);

  // 将分块数据写入文件
  $fp = fopen('uploads/' . $fileName . '.part' . $currentChunk, 'wb');
  fwrite($fp, $chunk);
  fclose($fp);

  $currentChunk++;
}

fclose($handle);

// 合并分块数据
$fp = fopen('uploads/' . $fileName, 'wb');
for ($i = 0; $i < $totalChunks; $i++) {
  $chunk = file_get_contents('uploads/' . $fileName . '.part' . $i);
  fwrite($fp, $chunk);
}
fclose($fp);

// 删除分块数据
for ($i = 0; $i < $totalChunks; $i++) {
  unlink('uploads/' . $fileName . '.part' . $i);
}

总结

通过使用 HTML5 File API 和 JavaScript,我们可以轻松实现前端大文件上传,并支持断点续传功能。这种方式可以极大地提高文件上传的效率和稳定性,非常适合处理大型文件上传场景。希望本文对您有所帮助,如果您有任何问题或建议,欢迎随时提出。