You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于react-dropzone实现文件上传进度(百分比/MB传输量)技术问询

Add Upload Progress Tracking to react-dropzone

Got it, let's tackle adding upload progress tracking (either percentage or transferred MB) to your react-dropzone setup. The core issue here is that the standard fetch API doesn't natively expose upload progress events, so we'll use XMLHttpRequest instead—it's straightforward and gives us direct access to progress updates. Here's how to adjust your existing code step by step:

Step 1: Add Progress Tracking State to Your Component

First, initialize state variables to keep track of upload progress and upload status:

constructor(props) {
  super(props);
  this.state = {
    filesToBeSent: [],
    filesPreview: [],
    showNotification: false,
    uploadResponse: null,
    fileType: false,
    fileSize: false,
    uploadProgress: 0, // Tracks upload percentage
    isUploading: false,
    transferredMB: 0 // Tracks data transferred in MB
  };
}

Step 2: Create a Progress-Enabled Upload Function

Replace or wrap your existing uploadApi with a function that uses XMLHttpRequest to listen for upload progress events:

uploadWithProgress(formData, onProgress) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    
    // Replace with your actual upload API endpoint
    xhr.open('POST', 'YOUR_UPLOAD_ENDPOINT_URL');
    
    // Listen for upload progress updates
    xhr.upload.addEventListener('progress', (event) => {
      if (event.lengthComputable) {
        const progressPercent = Math.round((event.loaded / event.total) * 100);
        const transferredMB = (event.loaded / (1024 * 1024)).toFixed(2);
        onProgress(progressPercent, transferredMB);
      }
    });
    
    // Handle successful upload
    xhr.onload = () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve(JSON.parse(xhr.responseText));
      } else {
        reject(new Error(`Upload failed with status ${xhr.status}`));
      }
    };
    
    // Handle network errors
    xhr.onerror = () => reject(new Error('Network error during upload'));
    
    xhr.send(formData);
  });
}

Step 3: Update the onDrop Method to Track Progress

Modify your onDrop function to start tracking progress when an upload begins, and update the state with real-time progress data:

onDrop(acceptedFiles) {
  const { filesToBeSent } = this.state;
  if (acceptedFiles.length) {
    const file = acceptedFiles[0];
    if (file.type === FileTypeList.TYPE) {
      // Reset progress state before starting upload
      this.setState({
        isUploading: true,
        uploadProgress: 0,
        transferredMB: 0,
        fileType: false,
        fileSize: false
      });

      const updatedFiles = [...filesToBeSent, file];
      const formData = new FormData();
      formData.append("file", file);

      // Use our progress-enabled upload function
      this.uploadWithProgress(formData, (progressPercent, transferredMB) => {
        this.setState({ uploadProgress: progressPercent, transferredMB });
      })
      .then((response) => {
        this.setState({
          filesPreview: [],
          filesToBeSent: [{}],
          showNotification: true,
          uploadResponse: response,
          isUploading: false
        });
        this.props.fetchHistory();
      })
      .catch((error) => {
        console.error('Upload failed:', error);
        this.setState({ isUploading: false });
        // Add custom error handling here (e.g., show an error notification)
      });
    } else {
      this.setState({ fileType: true, isUploading: false });
    }
  } else {
    this.setState({ fileSize: true, isUploading: false });
  }
}

Step 4: Display Progress in Your JSX

Update your Dropzone component to show the upload progress while the file is being uploaded:

<Dropzone maxSize={this.props.maxSize} onDrop={(files) => this.onDrop(files)}>
  {({ getRootProps, getInputProps }) => {
    return (
      <div {...getRootProps()} className={"dropzone"}>
        <UploadPanel id="uploadFileContainerId">
          {this.state.isUploading ? (
            <div className="upload-progress-container">
              <p>Upload Progress: {this.state.uploadProgress}%</p>
              <p>Transferred: {this.state.transferredMB} MB</p>
              {/* Basic progress bar - add CSS to style this */}
              <div className="progress-bar">
                <div 
                  className="progress-fill" 
                  style={{ width: `${this.state.uploadProgress}%` }}
                />
              </div>
            </div>
          ) : (
            <>
              <p>
                <img id="uploadImage" src={UploadImage} />
              </p>
              <input {...getInputProps()} />
              <div>{t("assets:UPLOAD_FILE")}</div>
              <Note>
                {this.props.maxSizeTitle ? t("workers:UPLOAD_WORKER_FILE_SIZE") : t("assets:UPLOAD_FILE_SIZE")}
              </Note>
            </>
          )}
        </UploadPanel>
      </div>
    );
  }}
</Dropzone>

Quick Notes:

  • Don't forget to replace YOUR_UPLOAD_ENDPOINT_URL in the uploadWithProgress function with your actual API endpoint.
  • The progress-bar and progress-fill classes are placeholders—add custom CSS to style them (e.g., a gray container with a colored fill that expands as progress increases).
  • If your existing uploadApi is a separate service, you can modify it to accept an onProgress callback instead of creating a new function, to keep your codebase consistent.

内容的提问来源于stack exchange,提问作者Arun Arya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:24:30