React组件,用于预览文件(PDF、Excel、Word、图片)

3,732 阅读2分钟

以下是一个简单的React组件,用于预览文件(PDF、Excel、Word、图片):

import React from 'react';

class FilePreview extends React.Component {
  render() {
    const { fileUrl, fileType } = this.props;

    if (fileType === 'image') {
      return <img src={fileUrl} alt="预览" />;
    }

    if (fileType === 'pdf') {
      return <embed src={fileUrl} type="application/pdf" width="100%" height="600px" />;
    }

    if (fileType === 'excel' || fileType === 'word') {
      return (
        <iframe 
          src={`https://view.officeapps.live.com/op/embed.aspx?src=${fileUrl}`} 
          width="100%" 
          height="600px" 
          frameBorder="0" 
        />
      );
    }

    return null;
  }
}

export default FilePreview;

使用方法:

import FilePreview from './FilePreview';

// 图片预览
<FilePreview fileUrl="https://example.com/image.jpg" fileType="image" />

// PDF预览
<FilePreview fileUrl="https://example.com/file.pdf" fileType="pdf" />

// Excel预览
<FilePreview fileUrl="https://example.com/file.xlsx" fileType="excel" />

// Word预览
<FilePreview fileUrl="https://example.com/file.docx" fileType="word" />

注意:

  1. 这个组件需要传入两个props:fileUrl(文件的URL)和fileType(文件类型)。
  2. 对于图片,我们使用<img>标签进行预览。
  3. 对于PDF,我们使用<embed>标签进行预览。
  4. 对于Excel和Word,我们使用Microsoft的在线预览服务,通过<iframe>标签进行预览。
  5. 请确保文件的URL是公开可访问的,否则可能无法预览。
  6. 由于跨域问题,某些文件可能无法在某些浏览器中预览。

在React中实现文件预览(pdf、excel、word、图片)可以使用第三方库,如 react-pdfreact-excel-renderermammoth.jsreact-image-gallery。以下是使用这些库的示例代码:

  1. PDF预览 - 使用 react-pdf
import { Document, Page } from 'react-pdf';

function MyApp() {
  return (
    <Document
      file="somefile.pdf"
    >
      <Page pageNumber={1} />
    </Document>
  );
}
  1. Excel预览 - 使用 react-excel-renderer
import ReactExcelRenderer from 'react-excel-renderer';

// excel文件数据
let fileObj = fileInput.files[0];

// 读取文件
let reader = new FileReader();
reader.onload = (event) => {
  let data = event.target.result;
  let workbook = ReactExcelRenderer.read(data, {type: 'binary'});

  // 预览excel文件
  workbook.SheetNames.forEach(sheet => {
    let rowObject = ReactExcelRenderer.utils.sheet_to_row_object_array(workbook.Sheets[sheet]);
    console.log(rowObject);
  });
};
reader.readAsBinaryString(fileObj);
  1. Word预览 - 使用 mammoth.js
import mammoth from 'mammoth';

mammoth.extractRawText({path: 'path/to/your/docx/file.docx'})
  .then(function(result){
    let text = result.value; // 文档的文本内容
    let messages = result.messages; // 任何解析警告
  })
  .done();
  1. 图片预览 - 使用 react-image-gallery
import ReactImageGallery from 'react-image-gallery';

const images = [
  {
    original: 'http://lorempixel.com/1000/600/nature/1/',
    thumbnail: 'http://lorempixel.com/250/150/nature/1/',
  },
  {
    original: 'http://lorempixel.com/1000/600/nature/2/',
    thumbnail: 'http://lorempixel.com/250/150/nature/2/'
  }
]

function MyApp() {
  return (
    <ReactImageGallery items={images} />
  );
}

以上代码只是简单的示例,实际使用时需要根据具体需求进行调整。同时,这些库可能存在兼容性问题,需要根据目标浏览器进行测试和调整。


可以将这些功能封装成一个React Hooks组件,并使用TypeScript进行类型检查,如下所示:

import React, { useState, useEffect } from 'react';
import { Document, Page } from 'react-pdf';
import ReactExcelRenderer from 'react-excel-renderer';
import mammoth from 'mammoth';
import ReactImageGallery from 'react-image-gallery';

interface FilePreviewProps {
  file: File;
}

const FilePreview: React.FC<FilePreviewProps> = ({ file }) => {
  const [fileType, setFileType] = useState<string>('');
  const [fileData, setFileData] = useState<any>(null);

  useEffect(() => {
    const fileType = file.name.split('.').pop().toLowerCase();
    setFileType(fileType);

    if (fileType === 'xlsx' || fileType === 'xls') {
      let reader = new FileReader();
      reader.onload = (event) => {
        let data = event.target.result;
        let workbook = ReactExcelRenderer.read(data, {type: 'binary'});
        setFileData(workbook);
      };
      reader.readAsBinaryString(file);
    } else if (fileType === 'docx') {
      mammoth.extractRawText({ arrayBuffer: file.arrayBuffer() })
        .then(result => setFileData(result.value));
    } else if (fileType === 'jpg' || fileType === 'png' || fileType === 'gif') {
      setFileData(URL.createObjectURL(file));
    }
  }, [file]);

  if (fileType === 'pdf') {
    return (
      <Document file={file}>
        <Page pageNumber={1} />
      </Document>
    );
  } else if (fileType === 'xlsx' || fileType === 'xls') {
    // 这里只是一个简单的示例,实际使用时可能需要更复杂的处理
    return (
      <div>
        {JSON.stringify(fileData)}
      </div>
    );
  } else if (fileType === 'docx') {
    return (
      <div>
        {fileData}
      </div>
    );
  } else if (fileType === 'jpg' || fileType === 'png' || fileType === 'gif') {
    return (
      <img src={fileData} alt="预览" />
    );
  } else {
    return null;
  }
};

export default FilePreview;

以上代码只是一个简单的示例,实际使用时可能需要更复杂的处理。同时,这些库可能存在兼容性问题,需要根据目标浏览器进行测试和调整。