swift, отправить файл на сервер

Я изучаю Swift и отправляю запрос на сервер с кодом ниже. Он работает для простого запроса, и я получаю ответ от сервера. Моя проблема в том, что я не могу отправить файл на сервер.

код :

let parameters = parameter

    let request = NSMutableURLRequest(URL: NSURL(string: requestUrl)!)
    let boundaryConstant = "-----Boundary+\(arc4random())\(arc4random())"


    let contentType = "multipart/form-data; boundary=" + boundaryConstant
    let boundaryStart = "--\(boundaryConstant)\r\n"
    let boundaryEnd = "--\(boundaryConstant)--\r\n"

    let body:NSMutableString = NSMutableString();

    for (key, value) in parameters {
        body.appendFormat(boundaryStart)
        body.appendFormat("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
        body.appendFormat("\(value)\r\n")
    }
    body.appendFormat(boundaryEnd)


    request.HTTPMethod = "POST"
    request.setValue(contentType, forHTTPHeaderField: "Content-Type")

    request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in

        guard error == nil && data != nil else {
            // check for fundamental networking error
            print("error=\(error)")
            return

        }


        if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 {           // check for http errors

            print("statusCode should be 200, but is \(httpStatus.statusCode)")
            print("response = \(response)")
        }


        self.responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
        print("MMMMMMMM \(self.responseString)")
        self.result = self.responseString.dataUsingEncoding(NSUTF8StringEncoding)! as NSData
        callback(self.responseString)

    }

    print("code start")
    task.resume()

результат: я могу отправить файл на сервер с помощью этого кода:

    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let request = createRequest()
    let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
        if error != nil {
            // handle error here
            print(error)
            return
        }
        do {
            if let responseDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
                print("success == \(responseDictionary)")

            }
        } catch {
            print(error)

            let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
            print("responseString = \(responseString)")
        }
    }
    task.resume()


}

func createRequest () -> NSURLRequest {
    let param = []


    let boundary = generateBoundaryString()

    let url = NSURL(string: "URl")!
    let request = NSMutableURLRequest(URL: url)
    request.HTTPMethod = "POST"
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    request.setValue("userValue", forHTTPHeaderField: "X-Client-user")
    request.setValue("passValue", forHTTPHeaderField: "X-Access-pass")


    //let path1 = NSBundle.mainBundle().pathForResource("voice", ofType: "png") as String!
    request.HTTPBody = createBodyWithParameters(param, filePathKey: "voice", paths: ["pathURl"], boundary: boundary)

    return request
}

func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, paths: [String]?, boundary: String) -> NSData {
    let body = NSMutableData()

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

    if paths != nil {
        for path in paths! {
            let url = NSURL(fileURLWithPath: path)
            let filename = url.lastPathComponent
            let data = NSData(contentsOfURL: url)!
            let mimetype = mimeTypeForPath(path)

            body.appendString("--\(boundary)\r\n")
            body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename!)\"\r\n")
            body.appendString("Content-Type: \(mimetype)\r\n\r\n")
            body.appendData(data)
            body.appendString("\r\n")
        }
    }

    body.appendString("--\(boundary)--\r\n")
    return body
}

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


func mimeTypeForPath(path: String) -> String {
    let url = NSURL(fileURLWithPath: path)
    let pathExtension = url.pathExtension

    if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension! as NSString, nil)?.takeRetainedValue() {
        if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
            return mimetype as String
        }
    }
    return "application/octet-stream";
}

person m-jamshidzadeh    schedule 24.02.2016    source источник
comment
В чем именно ошибка?   -  person JAL    schedule 24.02.2016
comment
у меня нет ошибок в этом коде, и этот код работает для меня, когда я отправляю запрос на сервер, и я получаю истинный ответ от сервера, теперь я не знаю, как отправить аудио ФАЙЛ на сервер   -  person m-jamshidzadeh    schedule 24.02.2016
comment
Вы должны быть более конкретными о вашей проблеме. Вы уже пробовали какой-либо подход? Если вы это сделали, но это не сработало, вы должны сообщить нам, что вы пробовали, чтобы можно было определить проблему. Если же вы не предпринимали никаких попыток самостоятельно, то вам следует сначала Google NSURLRequest прикрепить файл   -  person Andriy Gordiychuk    schedule 24.02.2016
comment
спасибо за ваш код результата, у меня тоже есть эта проблема, и это работает для меня   -  person Mohammad Tazehkar    schedule 29.02.2016
comment
Я попытался загрузить музыку с сервера в формате кодирования, а затем записать ее обратно, используя файловый поток, чтобы сохранить обратно в mp3. Я думаю, вы тоже можете попробовать, закодировать и отправить на сервер, а затем записать его с помощью файлового потока.   -  person Lee    schedule 09.03.2016


Ответы (2)


Как вы читаете здесь, вы должны использовать NSURLSession для работы с HTTP, он гораздо более гибкий и мощный; и я думаю суждено заменить NSURLconnection...

https://www.objc.io/issues/5-ios7/from-nsurlconnection-to-nsurlsession/

Вот вам пример...

 func getMetaData(lePath:String, completion: (string: String?, error: ErrorType?) -> Void) {
// **** get_metadata ****
    let request = NSMutableURLRequest(URL: NSURL(string: "https://api.dropboxapi.com/2/files/get_metadata")!)
    let session = NSURLSession.sharedSession()
    request.HTTPMethod = "POST"

    request.addValue("Bearer ab-blah-blah", forHTTPHeaderField: "Authorization")
    request.addValue("application/json",forHTTPHeaderField: "Content-Type")
    request.addValue("path", forHTTPHeaderField: lePath)
    let cursor:NSDictionary? = ["path":lePath]
    do {
        let jsonData = try NSJSONSerialization.dataWithJSONObject(cursor!, options: [])
        request.HTTPBody = jsonData
        print("json ",jsonData)
    } catch {
        print("snafoo alert")
    }

    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        if let error = error {
            completion(string: nil, error: error)
            return
        }
        let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
        print("Body: \(strData)\n\n")
        do {
            let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers);
            self.jsonParser(jsonResult,field2file: "ignore")
            for (key, value) in self.parsedJson {
                print("key2 \(key) value2 \(value)")
            }

            completion(string: "", error: nil)
        } catch {
            completion(string: nil, error: error)
        }
    })
    task.resume()

}
person user3069232    schedule 24.02.2016

Отличный ответ выше. Здесь он обновлен для Swift3:

 func getMetaData(lePath:String, completion: (string: String?, error: ErrorType?) -> Void) {
// **** get_metadata ****
    let request = NSMutableURLRequest(URL: NSURL(string: "https://api.dropboxapi.com/2/files/get_metadata")!)
    let session = NSURLSession.sharedSession()
    request.HTTPMethod = "POST"

    request.addValue("Bearer ab-blah-blah", forHTTPHeaderField: "Authorization")
    request.addValue("application/json",forHTTPHeaderField: "Content-Type")
    request.addValue("path", forHTTPHeaderField: lePath)
    let cursor:NSDictionary? = ["path":lePath]
    do {
        let jsonData = try NSJSONSerialization.dataWithJSONObject(cursor!, options: [])
        request.HTTPBody = jsonData
        print("json ",jsonData)
    } catch {
        print("snafoo alert")
    }

    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        if let error = error {
            completion(string: nil, error: error)
            return
        }
        let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
        print("Body: \(strData)\n\n")
        do {
            let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers);
            self.jsonParser(jsonResult,field2file: "ignore")
            for (key, value) in self.parsedJson {
                print("key2 \(key) value2 \(value)")
            }

            completion(string: "", error: nil)
        } catch {
            completion(string: nil, error: error)
        }
    })
    task.resume()

}
person ICL1901    schedule 28.01.2017
comment
что такое лепат? - person Yaroslav Dukal; 16.03.2018