1

I am trying to upload a photo to reqres to test URL request function.

Following a tutorial, I was able to test uploading a json file. And there was no problem with it.

But when I am trying to upload photo in a similar way, I am not getting a good response (nothing in the 200 range). Ultimately I am trying to upload a photo to AWS server (to an URL from API Gateway, this is also not working).

Following is what I used to test uploading json data

import SwiftUI
import Foundation 

struct CommentData: Encodable, Decodable {
    var comment: String
    var userId: String
}

struct TestUpload: View {
    @State private var confirmationMessage = ""
    @State private var showingConfirmation = false
    
    func uploadData() async {
        let replyToSend = CommentData(comment: "Hello from app", userId: "bkim")
        guard let encoded = try? JSONEncoder().encode(replyToSend) else {
            print("Failed to encode data")
            return
        }
        let url = URL(string: "https://reqres.in/api/bkim")!
        var request = URLRequest(url: url)
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        
        do {
            let (data, response) = try await URLSession.shared.upload(for: request, from: encoded)
            print(data)
            print(response)
            // It will automatically send back data
            let decodedData = try JSONDecoder().decode(CommentData.self, from: data)
            print(decodedData)
            confirmationMessage = "You received reply data with userID: \(decodedData.userId) desc: \(decodedData.comment)"
            showingConfirmation = true
        } catch {
            print("URL upload failed")
        }
    }
    
    var body: some View {
        ZStack {
            Image(imagePath)
            VStack {
                Spacer()
                Button(action: {Task{await uploadData()}}) {
                    Text("Upload")
                }
            }
        }
        .alert("Thank you!", isPresented: $showingConfirmation) {
            Button("OK") {}
        } message: {
            Text(confirmationMessage)
        }
    }
}

struct TestUpload_Previews: PreviewProvider {
    static var previews: some View {
        TestUpload()
    }
}

Uploading the json data works just fine. But if I try the same with image (I have image asset named PurpleAnnotated), it never works.

    private var imagePath = "PurpleAnnotated"
    
    func uploadImage() async {
        guard let problemPhoto = UIImage(named: self.imagePath) else {
            print("Failed to get photo")
            return
        }
        let imageData = problemPhoto.pngData()!
        
        let url = URL(string: "https://reqres.in/api/bkim")!
        var request = URLRequest(url: url)
        request.setValue("multipart/form-data", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"

        
        do {
            let (data, response) = try await URLSession.shared.upload(for: request, from: imageData)
            print(response)
            print(data)
            confirmationMessage = "You sent \(imageData) and received data: \(data)"
            showingConfirmation = true
        } catch {
            print("URL upload failed")
        }
        
    }
    

I tried various values for the setValue (blob/png, image/png, etc...) but I could never get it to work.

Is this not the right way to upload images? Any help would be greatly appreciated. I could not find any guide for this :( Any good documentation would also be appreciated. Thanks!

  • cannot see anything wrong with your code. In `uploadImage()` I used `guard let problemPhoto = UIImage(systemName: "globe")` in my tests, and all works well for me. I get a 201 response code, and an `id` and `createdAt` as the json data back from the server. Maybe your "PurpleAnnotated" is not there in your Assets. – workingdog support Ukraine Jul 15 '22 at 04:19
  • Interesting! I also tried with `UIImage(systemName: "house")` This worked. Trying the same thing with my custom seems to be the problem. I still don't understand why though. Because I can see the image of it `myImage = UIImage(named: "PurpleAnnotation")` `Image(uiImage: myImage ?? UIImage)` So it can certainly access the asset. But why does it fail when I try to upload it? – Wooshik Brian Kim Jul 19 '22 at 02:42
  • Try this, in `uploadImage`, add `print("\n---> data: \(String(data: data, encoding: .utf8)!)")` just after `let (data, response) = try await URLSession....`. In my tests with a `named` image, I get some html to say `Payload Too Large`. – workingdog support Ukraine Jul 20 '22 at 13:44

1 Answers1

0

I found the answer for this. For uploading to my server, the necessary request method was "PUT" not "POST". We thought we set it up as POST, but it was actually set up to take "PUT" for the particular URL.

For the reqres, I think the problem with custom photo upload was size. Testing with UIImage(systemName: "house") worked for reqres upload.