主要改动: 1. TCP缓冲区优化(16MB)- 解决公网上传速度慢问题 2. 并发数降低到1-3 - 避免4并发导致ERR_CONNECTION_RESET 3. 动态并发控制 - 根据网络环境自动调整 4. Nginx超时增加到120s - 支持大分片上传 5. 上传进度修复 - 修复剩余时间计算 6. 新增任务-页面上传器和详情组件 7. 统一部署文档为deploy-remote-build.ps1 问题修复: - 公网用户上传从200-900KB/s提升到预期3-5MB/s - 内网用户上传更稳定,无连接重置错误 - UploadProgress组件剩余时间计算修正 Co-Authored-By: Claude <noreply@anthropic.com>
182 lines
5.1 KiB
JavaScript
182 lines
5.1 KiB
JavaScript
#!/usr/bin/env node
|
||
|
||
/**
|
||
* 品牌VI灵感素材预览图诊断脚本
|
||
*
|
||
* 用途:检查生产环境中品牌VI灵感素材的预览图问题
|
||
* 运行:node scripts/diagnose-pdf.js
|
||
*/
|
||
|
||
const { PrismaClient } = require('@prisma/client')
|
||
const fs = require('fs/promises')
|
||
const path = require('path')
|
||
const { exec } = require('child_process')
|
||
const { promisify } = require('util')
|
||
|
||
const execAsync = promisify(exec)
|
||
|
||
const prisma = new PrismaClient()
|
||
|
||
// 问题素材ID列表
|
||
const PROBLEM_MATERIAL_IDS = [
|
||
'3ce99933-4df8-427f-aa30-454148025e1c',
|
||
'390fe674-a2a6-47f1-9b5d-6e377e5cac2c',
|
||
'fc8ab566-fd0b-4760-b68d-35a46c94d1bc',
|
||
'905b709d-74ab-4def-930b-ac5b86dfd381',
|
||
'64137416-3f37-4243-a72b-75f11f3a0114'
|
||
]
|
||
|
||
async function checkSystem() {
|
||
console.log('\n=== 系统环境检查 ===\n')
|
||
|
||
// 检查 pdftoppm 是否安装
|
||
try {
|
||
const { stdout } = await execAsync('which pdftoppm')
|
||
console.log('✅ pdftoppm 路径:', stdout.trim())
|
||
|
||
// 检查版本
|
||
try {
|
||
const { stdout: version } = await execAsync('pdftoppm -v')
|
||
console.log('✅ pdftoppm 版本信息:', version.split('\n')[0])
|
||
} catch (e) {
|
||
console.log('⚠️ 无法获取 pdftoppm 版本')
|
||
}
|
||
} catch (e) {
|
||
console.log('❌ pdftoppm 未安装或不在 PATH 中')
|
||
}
|
||
|
||
// 检查上传目录
|
||
const uploadDir = process.env.UPLOAD_DIR || './uploads'
|
||
console.log('\n上传目录配置:', uploadDir)
|
||
|
||
try {
|
||
const stats = await fs.stat(uploadDir)
|
||
console.log('✅ 上传目录存在,权限:', stats.mode.toString(8))
|
||
} catch (e) {
|
||
console.log('❌ 上传目录不存在或无权限访问')
|
||
}
|
||
|
||
// 检查临时目录
|
||
const tmpDir = require('os').tmpdir()
|
||
console.log('临时目录:', tmp_dir)
|
||
|
||
try {
|
||
await fs.access(tmpDir, fs.constants.W_OK)
|
||
console.log('✅ 临时目录可写')
|
||
} catch (e) {
|
||
console.log('❌ 临时目录不可写')
|
||
}
|
||
}
|
||
|
||
async function diagnoseMaterial(materialId) {
|
||
console.log(`\n${'='.repeat(60)}`)
|
||
console.log(`诊断素材: ${materialId}`)
|
||
console.log('='.repeat(60))
|
||
|
||
// 1. 查询数据库
|
||
const material = await prisma.material.findUnique({
|
||
where: { id: materialId },
|
||
include: {
|
||
assets: true,
|
||
skus: true
|
||
}
|
||
})
|
||
|
||
if (!material) {
|
||
console.log('❌ 素材不存在')
|
||
return
|
||
}
|
||
|
||
console.log('\n📊 数据库信息:')
|
||
console.log(' - 产品型号:', material.productModel)
|
||
console.log(' - 素材类型:', material.materialType)
|
||
console.log(' - 预览URL:', material.previewUrl || '(空)')
|
||
console.log(' - ZIP文件路径:', material.zipFilePath || '(空)')
|
||
console.log(' - ZIP文件名:', material.zipFileName || '(空)')
|
||
console.log(' - 资源数量:', material.assets.length)
|
||
console.log(' - SKU数量:', material.skus.length)
|
||
|
||
// 2. 检查 PDF 文件是否存在
|
||
const pdfPath = material.zipFilePath
|
||
if (!pdfPath) {
|
||
console.log('\n❌ 没有保存 PDF 文件路径')
|
||
return
|
||
}
|
||
|
||
console.log('\n📁 文件系统检查:')
|
||
console.log(' - PDF 路径:', pdfPath)
|
||
|
||
try {
|
||
const stats = await fs.stat(pdfPath)
|
||
console.log(' ✅ PDF 文件存在')
|
||
console.log(' - 文件大小:', (stats.size / 1024 / 1024).toFixed(2), 'MB')
|
||
console.log(' - 修改时间:', stats.mtime)
|
||
|
||
// 检查文件是否为有效 PDF
|
||
const handle = await fs.open(pdfPath, 'r')
|
||
const buffer = Buffer.alloc(4)
|
||
await handle.read(buffer, 0, 4, 0)
|
||
await handle.close()
|
||
|
||
const header = buffer.toString('ascii', 0, 4)
|
||
if (header === '%PDF') {
|
||
console.log(' ✅ 文件格式正确 (PDF)')
|
||
} else {
|
||
console.log(' ❌ 文件格式错误,期望 %PDF,实际:', header)
|
||
return
|
||
}
|
||
|
||
// 3. 尝试提取预览图
|
||
console.log('\n🖼️ 尝试提取 PDF 预览图...')
|
||
|
||
const { generatePdfPreview } = require('../lib/pdf-processor')
|
||
const result = await generatePdfPreview(pdfPath)
|
||
|
||
if (result.success) {
|
||
console.log(' ✅ PDF 预览图提取成功!')
|
||
console.log(' - 预览图路径:', result.previewPath)
|
||
console.log(' - 尺寸:', result.width, 'x', result.height)
|
||
|
||
// 读取预览图大小
|
||
const previewStats = await fs.stat(result.previewPath)
|
||
console.log(' - 文件大小:', (previewStats.size / 1024).toFixed(2), 'KB')
|
||
|
||
// 清理测试生成的预览图
|
||
await fs.unlink(result.previewPath).catch(() => {})
|
||
console.log(' ✅ 测试预览图已清理')
|
||
} else {
|
||
console.log(' ❌ PDF 预览图提取失败')
|
||
console.log(' - 错误信息:', result.error)
|
||
}
|
||
|
||
} catch (e) {
|
||
console.log(' ❌ 文件访问错误:', e.message)
|
||
}
|
||
}
|
||
|
||
async function main() {
|
||
console.log('🔍 品牌VI灵感素材预览图诊断工具')
|
||
console.log('时间:', new Date().toLocaleString('zh-CN'))
|
||
|
||
try {
|
||
// 检查系统环境
|
||
await checkSystem()
|
||
|
||
// 诊断每个问题素材
|
||
for (const id of PROBLEM_MATERIAL_IDS) {
|
||
await diagnoseMaterial(id)
|
||
}
|
||
|
||
console.log('\n' + '='.repeat(60))
|
||
console.log('✅ 诊断完成')
|
||
console.log('='.repeat(60) + '\n')
|
||
|
||
} catch (error) {
|
||
console.error('\n❌ 诊断过程出错:', error)
|
||
} finally {
|
||
await prisma.$disconnect()
|
||
}
|
||
}
|
||
|
||
main()
|