Reputation: 93
I am simply trying to store a static PDF in an S3 bucket which I can grab and present using Apple's built-in PDF Viewer. I am a having problems and a bit confused on a way to store the PDF locally in the proper form. I apologize if this is repeated or too simple, I have searched for hours on a proper solution but have not found anything that works. Thank you. I tried using the URL directly but that also threw an error.
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)
}
}
Upvotes: 1
Views: 1011
Reputation: 52645
Amplify.Storage.downloadData
returns a Data
object -- it doesn't actually download the file. But, there's another method downloadFile
that will work for this.
Your applications Bundle
has a static set of files. Once you save a file, you won't be looking in the Bundle, but rather in the app's documents or temp directory.
Rather than making the Amplify calls in the view body, probably better to assign it to a separate object (here I'm using an ObservableObject
called DataLoader
) to do the work at then set a flag (downloaded
) when it's done.
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()
}
}
}
Note: I have not tested the Amplify code; it is assumed to work as it is taken from https://docs.amplify.aws/lib/storage/download/q/platform/ios
Upvotes: 1