MST
星途 面试题库

面试题:React 文件上传事件中的错误处理及优化

在 React 处理文件上传事件时,可能会遇到网络错误、文件类型不匹配等问题。请阐述你如何设计错误处理机制,并说明如何优化文件上传过程以提高用户体验,比如进度条显示。
18.0万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

错误处理机制设计

  1. 网络错误处理
    • 使用 fetchaxios 进行文件上传时,在 catch 块中捕获网络错误。例如,使用 axios
    import axios from 'axios';
    const handleFileUpload = async (file) => {
      try {
        const formData = new FormData();
        formData.append('file', file);
        await axios.post('/upload', formData, {
          headers: {
            'Content-Type':'multipart/form-data'
          }
        });
      } catch (error) {
        if (error.response) {
          // 服务器返回了错误状态码
          console.error('服务器错误:', error.response.status);
        } else if (error.request) {
          // 请求已发出,但没有收到响应
          console.error('网络错误,没有收到响应');
        } else {
          // 其他错误
          console.error('请求设置时出错:', error.message);
        }
      }
    };
    
  2. 文件类型不匹配处理
    • 在上传前对文件类型进行验证。可以通过 input[type="file"]accept 属性来限制用户选择的文件类型,也可以在代码中手动验证。例如:
    const handleFileUpload = (file) => {
      const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
      if (!allowedTypes.includes(file.type)) {
        console.error('文件类型不匹配,仅允许', allowedTypes.join(', '), '类型的文件');
        return;
      }
      // 继续上传逻辑
    };
    
  3. 文件大小限制处理
    • 在上传前获取文件大小并进行限制。例如:
    const handleFileUpload = (file) => {
      const maxSize = 5 * 1024 * 1024; // 5MB
      if (file.size > maxSize) {
        console.error('文件大小超过限制,最大允许 5MB');
        return;
      }
      // 继续上传逻辑
    };
    

优化文件上传过程以提高用户体验

  1. 进度条显示
    • 使用 XMLHttpRequestfetchProgressEvent 来实现进度条。以 fetch 为例:
    const handleFileUpload = async (file) => {
      const formData = new FormData();
      formData.append('file', file);
      const controller = new AbortController();
      const { signal } = controller;
      const response = await fetch('/upload', {
        method: 'POST',
        body: formData,
        signal
      });
      const xhr = new XMLHttpRequest();
      xhr.open('POST', '/upload', true);
      xhr.upload.onprogress = function (e) {
        if (e.lengthComputable) {
          const percentComplete = (e.loaded / e.total * 100).toFixed(2);
          console.log('上传进度:', percentComplete + '%');
          // 在这里更新进度条 UI
        }
      };
      xhr.send(formData);
    };
    
  2. 并发控制
    • 如果有多个文件上传需求,可以限制并发数量,避免过多请求占用网络资源。例如,可以使用 Promise.allSettled 结合队列控制并发数:
    const uploadFiles = (files, maxConcurrent = 3) => {
      const queue = [];
      const results = [];
      for (let i = 0; i < files.length; i++) {
        const file = files[i];
        const uploadTask = () => {
          return new Promise((resolve, reject) => {
            // 上传逻辑,例如使用 axios
            const formData = new FormData();
            formData.append('file', file);
            axios.post('/upload', formData, {
              headers: {
                'Content-Type':'multipart/form-data'
              }
            })
             .then(() => resolve())
             .catch((error) => reject(error));
          });
        };
        queue.push(uploadTask);
      }
      const processQueue = async () => {
        while (queue.length > 0) {
          const currentTasks = queue.splice(0, maxConcurrent);
          const taskResults = await Promise.allSettled(currentTasks.map(task => task()));
          results.push(...taskResults);
        }
        return results;
      };
      return processQueue();
    };
    
  3. 用户反馈
    • 在上传开始时,显示加载指示器,告知用户上传正在进行。上传成功或失败后,给出明确的提示信息,如“文件上传成功”或“文件上传失败,请重试”。可以使用 React 的 useStateuseEffect 来管理和更新这些状态。
    import React, { useState, useEffect } from'react';
    const FileUploadComponent = () => {
      const [isUploading, setIsUploading] = useState(false);
      const [uploadStatus, setUploadStatus] = useState('');
      const handleFileUpload = (file) => {
        setIsUploading(true);
        // 上传逻辑
        setTimeout(() => {
          setIsUploading(false);
          setUploadStatus('文件上传成功');
        }, 3000);
      };
      return (
        <div>
          <input type="file" onChange={(e) => handleFileUpload(e.target.files[0])} />
          {isUploading && <p>上传中...</p>}
          {uploadStatus && <p>{uploadStatus}</p>}
        </div>
      );
    };
    export default FileUploadComponent;