ios - 从 S3 Bucket SwiftUI 下载公共 PDF 文件
问题描述
我只是想将静态 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)
}
}
解决方案
Amplify.Storage.downloadData
返回一个Data
对象——它实际上并不下载文件。但是,还有另一种方法downloadFile
可以解决这个问题。您的应用程序
Bundle
有一组静态文件。保存文件后,您将不会在 Bundle 中查找,而是在应用程序的文档或临时目录中查找。与其在视图主体中进行 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
推荐阅读
- r - 有什么方法可以从 R 中的累积 PCA 图中选择前 n 个 PCA 组件?
- javascript - 将百分比编码的表情符号显示为 html
- powershell - 将字符串转换为数据类型以存储在哈希表中
- java - GetByteArrayElements 未在此范围内声明
- maxima - 在最大值中通过引用调用:可能吗?
- javascript - 提交表单时如何轻松阻止页面重新加载?
- java - Java递归添加到列表
- html - 删除在我的容器内创建的空间
- tensorflow - 为什么我的自定义层在keras中失败了?
- regex - 带有通配符子域的 Apache http.conf