You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

5.8 KiB

Markdown 文件乱码问题排查指南

如果 Markdown 文件仍然显示乱码,请按以下步骤排查:


🔍 步骤 1:确认测试的是新文件

重要:修复后需要重新上传剧本文件,旧文件不会自动更新。

验证方法

  1. 删除或创建新剧本
  2. 上传新的 PDF/DOCX 文件(不要使用之前上传过的同一文件)
  3. 等待解析完成
  4. 获取新生成的 Markdown URL
  5. 在浏览器中打开测试

🔍 步骤 2:检查 HTTP 响应头

使用 curl 检查

# 替换为您的实际 Markdown 文件 URL
curl -I "https://oss-cn-beijing.aliyuncs.com/jointo/screenplays/.../xxx.md"

预期结果(正确)

HTTP/1.1 200 OK
Content-Type: text/markdown; charset=utf-8  ← ✅ 必须包含 charset=utf-8
Content-Disposition: inline
Content-Length: 12345
...

错误结果

HTTP/1.1 200 OK
Content-Type: text/markdown  ← ❌ 缺少 charset=utf-8

Content-Type: application/xml  ← ❌ 类型错误

如果是错误结果,说明 OSS 上传时的 Content-Type 设置未生效。


🔍 步骤 3:检查文件内容编码

下载文件并检查

# 下载 Markdown 文件
curl -o test.md "https://oss-cn-beijing.aliyuncs.com/jointo/screenplays/.../xxx.md"

# 检查文件编码
file -I test.md
# 预期输出:test.md: text/plain; charset=utf-8

使用 Python 检查

with open('test.md', 'rb') as f:
    content_bytes = f.read()
    
# 尝试 UTF-8 解码
try:
    content = content_bytes.decode('utf-8')
    print("✅ UTF-8 编码正常")
    print(content[:200])
except UnicodeDecodeError as e:
    print(f"❌ 编码错误: {e}")

🔍 步骤 4:检查原始 PDF/DOCX 编码

有时原始文件本身就有编码问题。

测试方法

  1. 用其他工具(如 Adobe Acrobat)打开原始 PDF
  2. 复制一段中文文本
  3. 粘贴到记事本,检查是否正常显示

如果原始文件有问题,需要:

  • 重新生成 PDF(确保使用 UTF-8 编码)
  • 或使用其他格式的剧本文件

🛠️ 解决方案

方案 1:强制重新解析(推荐)

# 在 Django shell 或 Python 脚本中执行
from app.tasks.screenplay_tasks import parse_screenplay_file_task
from app.models.screenplay import ParsingStatus

# 找到乱码的剧本
screenplay_id = "019c3272-3975-7372-a428-4790c30b7658"

# 重置解析状态
screenplay = await repo.get_by_id(screenplay_id)
await repo.update(screenplay_id, {
    'parsing_status': ParsingStatus.PENDING,
    'file_url': None,  # 清除旧的 Markdown URL
    'content': None
})

# 手动触发解析
parse_screenplay_file_task.delay(str(screenplay_id), "", "")

方案 2:手动修复 OSS 对象

如果文件内容编码正确,只是 Content-Type 头错误:

import boto3
from app.core.config import settings

s3_client = boto3.client(
    's3',
    endpoint_url=settings.S3_ENDPOINT_URL,
    aws_access_key_id=settings.S3_ACCESS_KEY_ID,
    aws_secret_access_key=settings.S3_SECRET_ACCESS_KEY,
    region_name=settings.S3_REGION
)

# 复制对象到自身,更新 Content-Type
object_key = "screenplays/.../xxx.md"

s3_client.copy_object(
    Bucket=settings.S3_BUCKET_NAME,
    CopySource={'Bucket': settings.S3_BUCKET_NAME, 'Key': object_key},
    Key=object_key,
    ContentType='text/markdown; charset=utf-8',
    ContentDisposition='inline',
    MetadataDirective='REPLACE'
)

方案 3:检查阿里云 OSS 配置

某些 OSS 配置可能覆盖 Content-Type:

  1. 登录阿里云控制台
  2. 进入 OSS Bucket 配置
  3. 检查"MIME 类型管理"
  4. 确保 .md 文件类型设置为 text/markdown; charset=utf-8

🧪 测试脚本

创建测试脚本验证编码链路:

# server/test_markdown_encoding.py
import asyncio
from app.core.storage import StorageService

async def test():
    storage = StorageService()
    
    # 测试内容(包含中文)
    test_content = "《狮子回头》\n\n这是测试内容。"
    content_bytes = test_content.encode('utf-8')
    
    # 上传
    object_name = "test/encoding_test.md"
    url = await storage.upload_bytes(
        data=content_bytes,
        object_name=object_name,
        content_type='text/markdown'
    )
    
    print(f"✅ 上传成功: {url}")
    print(f"完整 URL: https://oss-cn-beijing.aliyuncs.com/jointo/{object_name}")
    print("\n请在浏览器中打开上述 URL,检查中文是否正常显示")

asyncio.run(test())

运行:

cd /Users/panta/py_work/jointoai_work/Jointoai/server
docker compose exec app python test_markdown_encoding.py

📊 常见问题

Q1: 为什么旧文件不会自动修复?

A: OSS 对象的 metadata 是在上传时设置的,已上传的文件不会自动更新。

Q2: 浏览器显示正常,但下载后乱码?

A: 可能是下载工具或文本编辑器的默认编码不是 UTF-8。

解决

  • Windows 记事本:另存为 → 选择 UTF-8 编码
  • VS Code:右下角点击编码 → 选择 UTF-8

Q3: 某些中文字符正常,某些乱码?

A: 可能是原始 PDF 中使用了特殊字体或图片文字。

解决

  • 检查 PDF 是否包含嵌入字体
  • 使用 PDF 文字识别工具重新提取文本

Q4: curl 显示正确,浏览器显示乱码?

A: 浏览器可能缓存了旧的响应。

解决

  • 清除浏览器缓存
  • 强制刷新:Ctrl+Shift+R (Windows) 或 Cmd+Shift+R (Mac)
  • 使用隐身/无痕模式

🆘 仍然无法解决?

如果以上方法都无效,请提供:

  1. HTTP 响应头curl -I <url> 的完整输出)
  2. 文件的前 200 字节curl <url> | head -c 200 | xxd
  3. 原始 PDF 文件(用于本地测试)
  4. Celery 日志(解析任务的完整日志)

这将帮助我们进一步诊断问题。