fix(web): improve document preview handling for .doc files and validate docx format
- Add early return for .doc files with unsupported format message - Implement ZIP format validation for docx files by checking PK header bytes - Add error handling for invalid docx content with detailed error messages - Update Word preview UI to show download prompt for .doc files instead of attempting conversion - Prevent mammoth converter from processing invalid or non-docx file formats
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
* @Author: yujiangping
|
* @Author: yujiangping
|
||||||
* @Date: 2026-03-16 19:01:12
|
* @Date: 2026-03-16 19:01:12
|
||||||
* @LastEditors: yujiangping
|
* @LastEditors: yujiangping
|
||||||
* @LastEditTime: 2026-03-18 18:24:27
|
* @LastEditTime: 2026-03-18 18:35:53
|
||||||
*/
|
*/
|
||||||
import { useState, useEffect, useRef, useCallback, type FC } from 'react';
|
import { useState, useEffect, useRef, useCallback, type FC } from 'react';
|
||||||
import { Spin, Alert, Button, Table, InputNumber, Image } from 'antd';
|
import { Spin, Alert, Button, Table, InputNumber, Image } from 'antd';
|
||||||
@@ -286,7 +286,20 @@ const DocumentPreview: FC<DocumentPreviewProps> = ({
|
|||||||
setError(false);
|
setError(false);
|
||||||
setErrorMessage('');
|
setErrorMessage('');
|
||||||
try {
|
try {
|
||||||
|
// .doc 旧格式 mammoth 不支持,使用 Office Online Viewer
|
||||||
|
if (getFileExtension() === '.doc') {
|
||||||
|
setHtmlContent('');
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const arrayBuffer = await fetchFileBuffer(fileUrl);
|
const arrayBuffer = await fetchFileBuffer(fileUrl);
|
||||||
|
// 校验是否为有效的 docx(ZIP 格式,前两字节为 PK)
|
||||||
|
const header = new Uint8Array(arrayBuffer.slice(0, 4));
|
||||||
|
if (header[0] !== 0x50 || header[1] !== 0x4B) {
|
||||||
|
// 不是 ZIP/docx 格式,可能是 HTML 错误页或 JSON 响应
|
||||||
|
const text = new TextDecoder().decode(arrayBuffer.slice(0, 200));
|
||||||
|
throw new Error(`文件内容不是有效的 docx 格式: ${text.substring(0, 100)}`);
|
||||||
|
}
|
||||||
const result = await mammoth.convertToHtml({ arrayBuffer });
|
const result = await mammoth.convertToHtml({ arrayBuffer });
|
||||||
setHtmlContent(result.value);
|
setHtmlContent(result.value);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@@ -491,12 +504,22 @@ const DocumentPreview: FC<DocumentPreviewProps> = ({
|
|||||||
|
|
||||||
{/* Word 预览 */}
|
{/* Word 预览 */}
|
||||||
{isWordFile() && !error && !loading && (
|
{isWordFile() && !error && !loading && (
|
||||||
<div className="rb:w-full rb:flex-1 rb:overflow-auto rb:bg-white rb:p-6 rb:rounded rb:border rb:border-gray-200">
|
getFileExtension() === '.doc' ? (
|
||||||
<div
|
/* .doc 旧格式前端无法解析,提示下载 */
|
||||||
className="rb:prose rb:max-w-none"
|
<div className="rb:w-full rb:flex-1 rb:flex rb:items-center rb:justify-center rb:bg-gray-50">
|
||||||
dangerouslySetInnerHTML={{ __html: htmlContent }}
|
<div className="rb:text-center">
|
||||||
/>
|
<p className="rb:text-gray-600 rb:mb-4">.doc 格式暂不支持在线预览,请下载后查看</p>
|
||||||
</div>
|
<Button icon={<DownloadOutlined />} type="primary" onClick={handleDownload}>下载文件</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="rb:w-full rb:flex-1 rb:overflow-auto rb:bg-white rb:p-6 rb:rounded rb:border rb:border-gray-200">
|
||||||
|
<div
|
||||||
|
className="rb:prose rb:max-w-none"
|
||||||
|
dangerouslySetInnerHTML={{ __html: htmlContent }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Excel 预览 */}
|
{/* Excel 预览 */}
|
||||||
|
|||||||
Reference in New Issue
Block a user