正在从 S3 Bucket SwiftUI 下载 public 个 PDF 文件

Downloading public PDF file from S3 Bucket SwiftUI

我只是想将静态 PDF 存储在 S3 存储桶中,我可以使用 Apple 的内置 PDF 查看器获取和呈现它。我在以正确的形式在本地存储 PDF 的方法上遇到了问题并且有点困惑。如果重复或太简单,我深表歉意,我已经搜索了几个小时的适当解决方案,但没有找到任何有效的方法。谢谢你。我尝试直接使用 URL,但这也引发了错误。

import Amplify
import SwiftUI
import WebKit



struct ContentView: View {

    
    var body: some View {
        containedView()
        }
    
    func grabPDF(){
        Amplify.Storage.downloadData(
            key: "TermsOfUse.pdf"
        ){ result in
            switch result{
            case .success(let key):
                
                print("File with key: \(key)")
            case .failure(let storageError):
                print("Failed: ", storageError)
            }
        }
    }
    
    
    func containedView() -> WebView{
        grabPDF()
        return WebView(request: openPDF())
    }
    
    func openPDF() -> URLRequest{
        let path = Bundle.main.path(forResource: "TermsOfUse", ofType: "pdf")
        let url = URL(fileURLWithPath: path!)
        print(url)
        return URLRequest(url: url)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct WebView: UIViewRepresentable{
    let request: URLRequest
    
    func makeUIView(context: Context) -> WKWebView{
        return WKWebView()
    }
    
    func updateUIView(_ uiView: WKWebView, context: Context){
        uiView.load(request)
    }
}
  1. Amplify.Storage.downloadData returns 一个 Data 对象——它实际上并不下载文件。但是,还有另一种方法 downloadFile 可以解决这个问题。

  2. 您的应用程序 Bundle 有一组静态文件。保存文件后,您不会在 Bundle 中查找,而是在应用程序的文档或临时目录中查找。

  3. 与其在视图主体中进行 Amplify 调用,不如将其分配给单独的对象(此处我使用的是 ObservableObject 调用的 DataLoader)完成工作然后在完成后设置一个标志 (downloaded)。

class DataLoader : ObservableObject {
    @Published var downloaded : Bool = false
    
    func makeRequest() {
        let downloadToFileName = getTermsOfUseURL()

        Amplify.Storage.downloadFile(
            key: "TermsOfUse.pdf",
            local: downloadToFileName,
            progressListener: { progress in
                print("Progress: \(progress)")
            }, resultListener: { event in
                switch event {
                case .success:
                    print("Completed")
                    DispatchQueue.main.async { self.downloaded = true }
                case .failure(let storageError):
                    print("Failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)")
                }
            })
    }
    
    func getTermsOfUseURL() -> URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
        return paths[0].appendingPathComponent("TermsOfUse.pdf")
    }
}

struct ContentView: View {
    @ObservedObject var loader = DataLoader()
    
    var body: some View {
        VStack {
            if loader.downloaded {
                WebView(request: URLRequest(url: loader.getTermsOfUseURL()))
            }
        }.onAppear {
            loader.makeRequest()
        }
    }
}

注意:我没有测试过Amplify代码;假定它可以正常工作,因为它取自 https://docs.amplify.aws/lib/storage/download/q/platform/ios