2

I am trying to upload an image that is chosen from a UIImagePickerController to my web server hosted on AWS. I am following this tutorial: https://www.udemy.com/swift-php-mysql-user-sign-up-sign-in-sign-out-and-more/learn/v4/overview and I am getting a bunch of Argument labels '(_:)' do not match any available overloads errors. I've tried searching this error but I havent found anything that relates to my current code. I'm not using the original code in the tutorial, I'm trying to translate it to Swift3 and use the following answer: iOS swift NSMutableData has no member appendString to follow best coding practices. Here is my current code:

func createBodyWithParameters(_ parameters: [String: String]?, filePathKey: String?, imageDataKey: Data, boundary: String) -> Data {
        var body = Data();

        if parameters != nil {
            for (key, value) in parameters! {
                body.append(Data("--\(boundary)\r\n"))
                body.append(Data("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n"))
                body.append(Data("\(value)\r\n"))
            }
        }

        let filename = "user-profile.jpg"

        let mimetype = "image/jpg"

        body.append(Data("--\(boundary)\r\n"))
        body.append(Data("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n"))
        body.append(Data("Content-Type: \(mimetype)\r\n\r\n"))
        body.append(imageDataKey)
        body.append(Data("\r\n"))



        body.append(Data("--\(boundary)--\r\n"))

        return body as Data
    }

Can someone explain what I'm doing wrong? Thanks!

Community
  • 1
  • 1
Alan
  • 265
  • 1
  • 3
  • 15

3 Answers3

0

You cannot initialize Data like this:

Data("foo")

What you can do is:

Data("foo".utf8)

Like in the link you provided. (You are missing the .utf8)

EDIT: Yes the guy said he didn't want to use that code, but hear me out, this version of the extension doesn't allow lossy connection, and as long as you write anything inside the string, data will never be nil.

extension NSMutableData {
   func appendString(_ string: String) {
        let data = string.data(using: String.Encoding.utf8, allowLossyConversion: false)
        append(data!)
    }
}

Usage:

body.appendString("foo")

Just initialize body like this:

var body = NSMutableData()

And return like this

return body as Data
Nebojsa Nadj
  • 621
  • 3
  • 12
  • Hi @Nebojsa, I tried adding the utf8 at the end, but it still gives the same error. I was adding the Data because the guy in the other SO answer mentioned that you shouldn't use `body.append(string: "--\(boundary)\r\n")` What's the best practice when doing something like this? I'm still getting the same error though. Any ideas? – Alan May 15 '17 at 22:08
  • What exact error are you getting? I'll edit my answer soon, I have this code on my computer. – Nebojsa Nadj May 16 '17 at 04:57
  • Fixed the problem based on your answer. I used the second method with the extension and it worked like a charm. Thanks! – Alan May 16 '17 at 22:56
0

Try this code. You can use this code for uploading images to webserver in swift3

 func generateBoundaryString() -> String
{
    return "Boundary-\(NSUUID().uuidString)"
}

func photoDataToFormData(parameters: [String: String]?, data: Data, boundary:String, fileName:String) -> Data
{
    var fullData = Data()

    if parameters != nil {
        for (key, value) in parameters! {

            print ("Key: \(key), Value: \(value)")
            let str = "--\(boundary)\r\n" + "Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n" + "\(value)\r\n"
            let data = str.data(using: String.Encoding.utf8, allowLossyConversion: true)

            fullData.append(data!)
        }
    }

    // 1 - Boundary should start with --
    let lineOne = "--" + boundary + "\r\n"
    fullData.append(lineOne.data(using: String.Encoding.utf8, allowLossyConversion: false)!)

    // 2
    let lineTwo = "Content-Disposition: form-data; name=\"image\"; filename=\"" + fileName + "\"\r\n"
    NSLog(lineTwo)
    fullData.append(lineTwo.data(using: String.Encoding.utf8, allowLossyConversion: false)!)

    // 3
    let lineThree = "Content-Type: image/jpg\r\n\r\n"
    fullData.append(lineThree.data(using: String.Encoding.utf8, allowLossyConversion: false)!)

    // 4
    fullData.append(data)

    // 5
    let lineFive = "\r\n"
    fullData.append(lineFive.data(using: String.Encoding.utf8, allowLossyConversion: false)!)

    // 6 - The end. Notice -- at the start and at the end
    let lineSix = "--" + boundary + "--\r\n"
    fullData.append(lineSix.data(using: String.Encoding.utf8, allowLossyConversion: false)!)
    return fullData
}

After the above code you need to call a function before the task in the Api function. I have mention that code below.

 let imageData = UIImageJPEGRepresentation(profileImage.image!, 0.5)

 let boundary = generateBoundaryString()

 let fullData = photoDataToFormData(parameters: parameters as? [String : 
 String], data: imageData!, boundary: boundary, fileName: "Test.jpg")

 request.setValue("multipart/form-data; boundary=" + boundary, 
 forHTTPHeaderField: "Content-Type")

    // REQUIRED!
 request.setValue(String(fullData.count), forHTTPHeaderField: "Content-
 Length")

 request.httpBody = fullData
Wide Angle Technology
  • 1,184
  • 1
  • 8
  • 28
0

I has solved This problem in swift 4 by adding the following lines after class ViewController:

func generateBoundaryString() -> String {
    return "Boundary-\(NSUUID().uuidString)"
}

extension NSMutableData {
    func appendString(string: String) {
        let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
        append(data!)
    }
}

I mean class Viewcontroller the class that created when you add ViewController to your project. example next class:

   class ViewController2: UIViewController ,UINavigationControllerDelegate , UIImagePickerControllerDelegate{
      // my code
    }
khaled Debuch
  • 53
  • 2
  • 6