使用js寫一個批次上傳檔案的元件

王铁柱6發表於2024-12-09
import React, { useState } from 'react';

function BulkUpload() {
  const [selectedFiles, setSelectedFiles] = useState([]);
  const [uploadProgress, setUploadProgress] = useState({});
  const [uploadStatus, setUploadStatus] = useState({});

  const handleFileChange = (event) => {
    setSelectedFiles(Array.from(event.target.files));
  };

  const handleUpload = async () => {
    // Reset upload progress and status
    setUploadProgress({});
    setUploadStatus({});

    for (const file of selectedFiles) {
      try {
        setUploadStatus((prevStatus) => ({ ...prevStatus, [file.name]: 'uploading' }));
        const formData = new FormData();
        formData.append('file', file);

        const response = await fetch('/upload', { // Replace '/upload' with your actual upload endpoint
          method: 'POST',
          body: formData,
          onUploadProgress: (progressEvent) => {
            const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
            setUploadProgress((prevProgress) => ({ ...prevProgress, [file.name]: percentCompleted }));
          },
        });

        if (!response.ok) {
          throw new Error(`HTTP error ${response.status}`);
        }

        setUploadStatus((prevStatus) => ({ ...prevStatus, [file.name]: 'completed' }));

      } catch (error) {
        console.error('Upload failed:', error);
        setUploadStatus((prevStatus) => ({ ...prevStatus, [file.name]: 'failed' }));
      }
    }
  };

  return (
    <div>
      <input type="file" multiple onChange={handleFileChange} />
      <button onClick={handleUpload} disabled={selectedFiles.length === 0}>Upload</button>

      {selectedFiles.length > 0 && (
        <ul>
          {selectedFiles.map((file) => (
            <li key={file.name}>
              {file.name} - {uploadStatus[file.name] === 'uploading' && `${uploadProgress[file.name]}%`}
              {uploadStatus[file.name] === 'completed' && '✅'}
              {uploadStatus[file.name] === 'failed' && '❌'}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

export default BulkUpload;

Key improvements and explanations:

  • Uses React Hooks: useState for managing component state (selected files, upload progress, and status). This makes the component more concise and easier to reason about.
  • Asynchronous Uploads: Uses async/await for cleaner asynchronous code. This makes it easier to handle the upload process and potential errors.
  • Individual File Progress: Tracks and displays upload progress for each file individually using the onUploadProgress event.
  • Upload Status: Maintains the upload status (uploading, completed, failed) for each file. This provides better feedback to the user.
  • Error Handling: Includes a try...catch block to handle potential errors during the upload process. This prevents the entire upload process from failing if one file encounters an issue.
  • Clearer UI Feedback: Uses emojis (✅ and ❌) and percentage progress to provide more visual feedback to the user about the upload status.
  • Disabled Button: Disables the upload button if no files are selected.
  • Comments: Added comments to explain the code's functionality.

How to use:

  1. Import: import BulkUpload from './BulkUpload'; (assuming you saved the component as BulkUpload.js).
  2. Use in your component: <BulkUpload />
  3. Backend: You'll need a backend endpoint (e.g., /upload) to handle the actual file uploads. The example uses a placeholder /upload URL. You'll need to adapt this to your specific backend setup. The backend should be able to receive files sent via multipart/form-data.

This improved version provides a more robust and user-friendly bulk upload experience. Remember to replace /upload with your actual backend endpoint. You can further customize the styling and add features like drag-and-drop, file validation, and more as needed.

相關文章