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

Xcode14.3开发iOS App:文件权限未显示、PDF下载保存异常求助

iOS Web App PDF下载问题解决方案

一、先解决系统设置无权限显示问题

在info.plist中添加以下权限描述键值对,否则系统不会在设置中显示App的文件访问权限:

<key>NSDocumentsFolderUsageDescription</key>
<string>需要访问文档目录以保存下载的PDF文件</string>
<key>NSDownloadsFolderUsageDescription</key>
<string>需要访问下载目录以保存PDF文件</string>
<key>UIFileSharingEnabled</key>
<true/>
  • UIFileSharingEnabled开启后,你的App会在系统「文件」App中显示,方便用户管理文件;
  • 权限描述字符串要明确说明用途,否则Apple审核可能不通过。

二、修复WKWebView下载处理逻辑

如果你用的是UIWebView,立刻换成WKWebView(UIWebView已废弃)。以下是完整的下载处理代码示例:

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate, WKDownloadDelegate, UIDocumentPickerDelegate {
    private var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupWebView()
        loadWebApp()
    }

    private func setupWebView() {
        let config = WKWebViewConfiguration()
        webView = WKWebView(frame: view.bounds, configuration: config)
        webView.navigationDelegate = self
        webView.downloadDelegate = self // 必须设置下载代理才能处理PDF下载
        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(webView)
    }

    private func loadWebApp() {
        guard let url = URL(string: "你的WebApp地址") else { return }
        webView.load(URLRequest(url: url))
    }

    // 拦截下载请求
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: @escaping (WKNavigationActionPolicy, WKWebpagePreferences) -> Void) {
        guard let response = navigationAction.response as? HTTPURLResponse else {
            decisionHandler(.allow, preferences)
            return
        }
        
        // 通过响应头判断是否为附件下载(PDF通常会返回Content-Disposition: attachment)
        let contentDisposition = response.allHeaderFields["Content-Disposition"] as? String ?? ""
        if contentDisposition.contains("attachment") {
            webView.startDownload(using: navigationAction.request)
            decisionHandler(.cancel, preferences) // 取消默认导航,避免WebView跳转
            return
        }
        
        decisionHandler(.allow, preferences)
    }

    // 下载完成后处理文件
    func download(_ download: WKDownload, didFinishDownloadingTo location: URL) {
        let fileManager = FileManager.default
        guard let documentsDir = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
        
        // 用服务器返回的文件名,默认取downloaded.pdf
        let fileName = download.response.suggestedFilename ?? "downloaded.pdf"
        let destURL = documentsDir.appendingPathComponent(fileName)
        
        // 先删除已存在的同名文件
        if fileManager.fileExists(atPath: destURL.path) {
            try? fileManager.removeItem(at: destURL)
        }
        
        // 移动临时下载文件到App沙盒目录
        do {
            try fileManager.moveItem(at: location, to: destURL)
            showSavePicker(for: destURL) // 弹出选择器让用户选择保存路径
        } catch {
            print("保存文件失败:\(error)")
        }
    }

    // 弹出文件选择器供用户选择保存路径
    private func showSavePicker(for fileURL: URL) {
        let picker = UIDocumentPickerViewController(forExporting: [fileURL], asCopy: true)
        picker.delegate = self
        picker.modalPresentationStyle = .formSheet
        present(picker, animated: true)
    }

    // 文件选择器代理方法
    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        print("文件已成功保存到:\(urls.first?.path ?? "")")
        dismiss(animated: true)
    }

    func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
        dismiss(animated: true)
    }
}

三、关键注意事项

  1. 必须设置WKDownloadDelegate:WKWebView不会自动处理下载请求,需要通过代理拦截并触发下载;
  2. 临时文件处理:下载完成的文件会存放在临时目录,必须移动到沙盒或通过文件选择器导出,否则App重启后文件会被系统删除;
  3. 权限触发时机:只有当App实际访问对应目录(比如代码中访问documentDirectory),且info.plist有对应描述时,系统设置才会显示文件访问权限;
  4. iOS版本兼容性:上述代码适配iOS13+,Xcode14.3对应的iOS16完全支持。

内容的提问来源于stack exchange,提问作者Thiruselvam B

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 05:43:22