React + Node 实现大文件分片上传、断点续传、秒传[多个文件]

效果图:

QQ20221129-170230-HD

react

  1. html
    <div style={
  { padding: 30 }}>
      <h1>
        React + Node 实现大文件分片上传、断点续传、秒传[多个文件]:
        <input ref={inputRef} type="file" id="file" multiple />
        <Button type="primary" onClick={() => inputRef.current.click()}>
          上传
        </Button>
      </h1>

      {state.checkPercentList.length > 0 && (
        <div>
          <h3 style={
  { width: 200 }}>读取文件:</h3>
          <div style={
  { display: 'flex', flexWrap: 'wrap' }}>
            {state.checkPercentList.map((c) => (
              <div style={
  { width: '20%' }} key={c.name}>
                文件名:{c.name}
                <br />
                <Progress style={
  { width: '90%' }} percent={c.progress} />
              </div>
            ))}
          </div>
        </div>
      )}

      {state.uploadPercentList.length > 0 && (
        <div>
          <h3 style={
  { width: 200 }}>上传文件进度:</h3>
          <div style={
  { display: 'flex', flexWrap: 'wrap' }}>
            {state.uploadPercentList.map((c) => (
              <div style={
  { width: '20%' }} key={c.name}>
                文件名:{c.name}
                <br />
                <Progress style={
  { width: '90%' }} percent={c.progress} />
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  1. 上传文件(多文件)
  useEffect(() => {
    // if (renderRef.current) {
    //   renderRef.current = false;
    //   return;
    // }

    const changeFile = ({ target }) => {
      dispatch({ type: 'clearAll' });

      for (let i = 0; i < target.files.length; i++) {
        dispatch({ type: 'init'
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个使用React函数式组件实现断点续传分片上传的示例代码,同时还实现上传过的分片不再上传的功能。 ``` import React, { useState } from 'react'; import axios from 'axios'; function Upload() { const [selectedFile, setSelectedFile] = useState(null); const [uploaded, setUploaded] = useState(false); const [progress, setProgress] = useState(0); const handleFileSelect = (event) => { setSelectedFile(event.target.files[0]); }; const handleUpload = async () => { if (!selectedFile) { alert('请选择文件'); return; } const fileSize = selectedFile.size; const fileName = selectedFile.name; // 下面这段代码可以判断文件是否已经上传过,如果已经上传过, // 则直接返回,不需要再次上传实现功能 const res = await axios.get(`/check-file/${fileName}`); if (res.data && res.data.isUploaded) { setUploaded(true); return; } // 计算需要分片的总数 const chunkSize = 2 * 1024 * 1024; // 每个分片的大小为2MB const totalChunks = Math.ceil(fileSize / chunkSize); // 生成上传任务ID const taskId = Math.random().toString(36).slice(2); // 创建上传任务 await axios.post('/create-task', { taskId, fileName, fileSize, totalChunks, }); // 获取已上传分片列表 const uploadedChunksRes = await axios.get(`/get-uploaded-chunks/${taskId}`); const uploadedChunks = uploadedChunksRes.data; // 上传上传过的分片 let uploadedChunksCount = 0; for (let i = 0; i < totalChunks; i++) { if (uploadedChunks.includes(i)) { uploadedChunksCount += 1; continue; } const start = i * chunkSize; const end = Math.min(start + chunkSize, fileSize); const chunk = selectedFile.slice(start, end); const formData = new FormData(); formData.append('file', chunk, fileName); formData.append('taskId', taskId); formData.append('chunkIndex', i); await axios.post('/upload-chunk', formData, { onUploadProgress: (progressEvent) => { const loaded = progressEvent.loaded; const total = progressEvent.total; const percent = Math.round((loaded / total) * 100); setProgress(percent); }, }); uploadedChunksCount += 1; // 每上传10个分片,就更新一次数据库中的上传进度 if (uploadedChunksCount % 10 === 0) { await axios.post('/update-progress', { taskId, progress: Math.round((uploadedChunksCount / totalChunks) * 100), }); } } // 标记文件上传完成 await axios.post('/upload-finish', { taskId, }); setUploaded(true); }; return ( <div> <input type="file" onChange={handleFileSelect} /> <button onClick={handleUpload}>上传</button> {progress > 0 && progress < 100 && ( <p>上传进度:{progress}%</p> )} {uploaded && ( <p>上传完成</p> )} </div> ); } export default Upload; ``` 在上面的代码中,我们首先通过`useState`来管理组件状态。当用户选择了文件后,我们会通过`handleFileSelect`函数将文件信息保存到`selectedFile`状态中。然后,当用户点击上传按钮时,我们会根据文件大小和文件名等信息,计算出需要分片的总数,并生成一个上传任务ID。接下来,我们会先检查文件是否已经上传过,如果已经上传过,则直接返回,实现功能。如果文件没有上传过,则创建一个上传任务,并获取已经上传过的分片列表。然后,我们会循环上传每个未上传过的分片。每上传完10个分片,就会更新一次数据库中的上传进度。最后,当所有分片上传完成后,我们会标记文件上传完成,并显示上传完成的提示信息。 需要注意的是,在上面的代码中,我们使用了`axios`库来发起HTTP请求,但是具体的上传断点续传逻辑需要配合后端实现。此外,我们还需要在后端实现获取已上传分片列表的接口,并将已上传分片保存到数据库中,以便前端在上传时进行判断。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值