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

SwiftUI导入导出PDF及Word文档功能异常问题咨询

问题根源
  • 你当前的MessageDocument是专为纯文本格式设计的,只能读写UTF8编码的字符串,PDF、doc属于二进制文件,直接将二进制数据转为UTF8字符串会失败,所以document一直保留初始的"Hello World"值,导出自然只有这段文本
  • 原有fileImporter逻辑错误将二进制文件内容强制转UTF8字符串,fileExporter也没有指定对应二进制文件的正确类型
修复步骤

1. 重构MessageDocument支持二进制文件

替换原有MessageDocument代码,改为存储二进制Data而非纯文本String:

import SwiftUI
import UniformTypeIdentifiers

struct GeneralDocument: FileDocument {
    // 支持的导入格式:可按需增删
    static var readableContentTypes: [UTType] {
        [.pdf, .docx, UTType("com.microsoft.word.doc")!, .plainText]
    }
    
    // 存储文件二进制原始数据
    var fileData: Data
    // 可选:存储文件类型,导出时用
    var fileType: UTType?

    init(data: Data, type: UTType? = nil) {
        self.fileData = data
        self.fileType = type
    }

    init(configuration: ReadConfiguration) throws {
        guard let data = configuration.file.regularFileContents else {
            throw CocoaError(.fileReadCorruptFile)
        }
        self.fileData = data
        self.fileType = configuration.contentType
    }

    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        return FileWrapper(regularFileWithContents: fileData)
    }
}

2. 修改声明的document属性

// 替换原有MessageDocument声明
@State private var document: GeneralDocument = GeneralDocument(data: "Hello, World!".data(using: .utf8)!)
// 可选:存储导入的文件名,导出时复用
@State private var importedFileName: String?

3. 修正fileImporter逻辑

删除二进制转UTF8字符串的错误逻辑,直接读取原始Data:

.fileImporter(
    isPresented: $isImporting,
    // 支持导入的格式和GeneralDocument里保持一致
    allowedContentTypes: GeneralDocument.readableContentTypes,
    allowsMultipleSelection: false
) { result in
    do {
        guard let selectedFile: URL = try result.get().first else { return }
        if selectedFile.startAccessingSecurityScopedResource() {
            defer {
                selectedFile.stopAccessingSecurityScopedResource()
            }
            // 直接读取二进制原始数据
            let fileData = try Data(contentsOf: selectedFile)
            // 获取文件类型
            let fileType = UTType(filenameExtension: selectedFile.pathExtension)
            // 存储文件名
            importedFileName = selectedFile.deletingPathExtension().lastPathComponent
            // 赋值给document
            document = GeneralDocument(data: fileData, type: fileType)
        } else {
            print("Permission error!")
        }
    } catch {
        print(error.localizedDescription)
    }
}

4. 修正fileExporter配置

指定正确的导出类型和文件名:

.fileExporter(
    isPresented: $isExporting,
    document: document,
    // 导出用导入的文件类型,默认PDF可自行修改
    contentType: document.fileType ?? .pdf,
    // 复用导入的文件名,默认名自行修改
    defaultFilename: importedFileName ?? "导出文件"
) { result in
    switch result {
    case .success(let url):
        print("导出成功: \(url)")
    case .failure(let error):
        print("导出失败: \(error.localizedDescription)")
    }
}
补充说明
  • 如果仅需要支持PDF格式,可删除readableContentTypes里的doc、docx相关类型
  • 导入doc格式需要注意:系统原生UTType没有直接提供.doc常量,需要用UTType("com.microsoft.word.doc")!手动声明
  • 导出不同格式时可自行修改contentType参数,对应导出正确的文件后缀

内容的提问来源于stack exchange,提问作者Mert Köksal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 11:48:03