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

React实现图片与PDF上传及预览功能求助(含库推荐)

Hey there! Since you're new to React, I'll break this down step by step so it's easy to follow. Let's start with a no-library basic implementation first, then move to recommended libraries that'll make this even smoother.

1. Basic React Implementation (No External Libraries)

This approach is great for learning how things work under the hood. Here's how to modify your existing code to support both images and PDFs, plus add previews:

Step 1: Set Up State

We'll use React's useState to track uploaded files and their previews, plus useEffect to clean up memory leaks:

import { useState, useEffect } from 'react';

function FileUploader() {
  const [uploadedFiles, setUploadedFiles] = useState([]);

  // Clean up preview URLs when the component unmounts
  useEffect(() => {
    return () => {
      uploadedFiles.forEach(file => URL.revokeObjectURL(file.previewUrl));
    };
  }, [uploadedFiles]);

  // ... rest of the code
}

Step 2: Handle File Selection & Validation

Update the file input to accept both images and PDFs, then filter out invalid files:

const handleFileChange = (e) => {
  const files = Array.from(e.target.files);
  
  // Only keep images and PDFs
  const validFiles = files.filter(file => {
    return file.type.startsWith('image/') || file.type === 'application/pdf';
  });

  // Generate preview URLs for each valid file
  const filesWithPreviews = validFiles.map(file => ({
    file,
    previewUrl: URL.createObjectURL(file),
    type: file.type.startsWith('image/') ? 'image' : 'pdf'
  }));

  setUploadedFiles(prev => [...prev, ...filesWithPreviews]);
};

Step 3: Render Previews

Display different previews based on file type (image tags for images, iframes for PDFs):

const renderPreviews = () => {
  return uploadedFiles.map((item, index) => (
    <div key={index} style={{ margin: '10px', padding: '10px', border: '1px solid #ddd' }}>
      <p>{item.file.name}</p>
      {item.type === 'image' ? (
        <img 
          src={item.previewUrl} 
          alt={item.file.name} 
          style={{ maxWidth: '300px', maxHeight: '300px' }}
        />
      ) : (
        <iframe 
          src={item.previewUrl} 
          title={item.file.name} 
          style={{ width: '300px', height: '400px', border: '1px solid #ccc' }}
        />
      )}
      {/* Optional: Add a delete button */}
      <button onClick={() => removeFile(index)} style={{ marginTop: '10px' }}>
        Remove
      </button>
    </div>
  ));
};

const removeFile = (index) => {
  const fileToRemove = uploadedFiles[index];
  URL.revokeObjectURL(fileToRemove.previewUrl); // Clean up preview
  setUploadedFiles(prev => prev.filter((_, i) => i !== index));
};

Step 4: Add the File Input

Put it all together with the input element:

return (
  <div>
    <input 
      type="file" 
      multiple 
      accept="image/*, application/pdf" 
      onChange={handleFileChange}
    />
    <div style={{ marginTop: '20px' }}>
      {uploadedFiles.length > 0 ? (
        renderPreviews()
      ) : (
        <p>No files uploaded yet</p>
      )}
    </div>
  </div>
);

If you want to skip boilerplate and add features like drag-and-drop, these libraries are perfect for React beginners:

Lightweight, flexible, and handles file validation, drag-and-drop, and previews out of the box.

Installation:

npm install react-dropzone

Basic Example:

import { useDropzone } from 'react-dropzone';

function DropzoneUploader() {
  const { getRootProps, getInputProps, acceptedFiles } = useDropzone({
    accept: {
      'image/*': [],
      'application/pdf': []
    }
  });

  const filesWithPreviews = acceptedFiles.map(file => ({
    file,
    previewUrl: URL.createObjectURL(file),
    type: file.type.startsWith('image/') ? 'image' : 'pdf'
  }));

  return (
    <div>
      <div {...getRootProps({ style: { border: '2px dashed #ccc', padding: '20px', textAlign: 'center' } })}>
        <input {...getInputProps()} />
        <p>Drag & drop files here, or click to select</p>
        <p>(Supports images and PDFs)</p>
      </div>
      <div style={{ marginTop: '20px' }}>
        {filesWithPreviews.map((item, index) => (
          <div key={index} style={{ margin: '10px' }}>
            <p>{item.file.name}</p>
            {item.type === 'image' ? (
              <img src={item.previewUrl} alt={item.file.name} style={{ maxWidth: '300px' }} />
            ) : (
              <embed src={item.previewUrl} style={{ width: '300px', height: '400px' }} />
            )}
          </div>
        ))}
      </div>
    </div>
  );
}

react-file-viewer (For Advanced Previews)

Great if you need PDF controls like zoom or page navigation, or support for more file types.

Installation:

npm install react-file-viewer

Usage Example:

import FileViewer from 'react-file-viewer';

// Inside your preview component:
<FileViewer
  fileType={item.file.type === 'application/pdf' ? 'pdf' : 'image'}
  filePath={item.previewUrl}
  onError={(e) => console.error('Preview error:', e)}
/>

Powerful option if you need progress bars, upload cancellation, or cloud storage integration. It's more complex but scales well for larger projects.

3. Key Notes for Beginners

  • Validate files on the backend too: Frontend validation is for user experience only—never trust it alone; your server should double-check file types and sizes.
  • Clean up preview URLs: Always use URL.revokeObjectURL when removing files or unmounting components to avoid memory leaks.
  • PDF preview fixes: If browsers have trouble rendering PDFs, try the react-pdf library for better, more reliable PDF rendering.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:24:40