Как загрузить изображение с помощью json?


Я пытаюсь загрузить изображение с данными json. Я просто следовал посту и реализовал механизм. Но я получаю ошибку

{ status code: 400, headers {
    "Cache-Control" = "no-cache, no-store, max-age=0, must-revalidate";
    Connection = close;
    "Content-Language" = en;
    "Content-Length" = 1033;
    "Content-Type" = "text/html;charset=utf-8";
    Date = "Wed, 27 Jan 2016 10:44:34 GMT";
    Expires = 0;
    Pragma = "no-cache";
    Server = "Apache-Coyote/1.1";
    "X-Content-Type-Options" = nosniff;
    "X-XSS-Protection" = "1; mode=block";
} }`

Ниже приведен полный HTTP-запрос

Content-Type: multipart/form-data;boundary=Boundary_123456789
Authorization: Basic bihdwbcIUkbcdwjnoNOn
User-Agent: Jersey/2.21.1 (HttpUrlConnection 1.8.0_45)
MIME-Version: 1.0
Host: localhost:8080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 3526

--Boundary_123456789
Content-Type: application/json
Content-Disposition: form-data; name="userDTO"

{"id":"id","name":"name","age":23}
--Boundary_123456789
Content-Type: image/png
Content-Disposition: form-data; filename="sample-image2.png"; modification-date="Fri, 22 Jan 2016 04:56:48 GMT"; size=3308; name="file"

‰PNG

<Binary data>

--Boundary_123456789—

Ниже приведена моя реализация

func addUser(completion: (message: String?, error: String?) -> Void) -> NSURLSessionDataTask {
        // create the request            
        let request = createRequest()

        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
            print(response) // 400 Error is printed here
        }
        task.resume()

        return task
    }
func createRequest () -> NSURLRequest {
    let param = [
        "id": "id",
        "name": "name",
        "age": 23]  // build your dictionary however appropriate

    let boundary = generateBoundaryString()

    let url = NSURL(string: SERVERURL)!
    let request = NSMutableURLRequest(URL: url)
    request.HTTPMethod = "POST"
    request.addValue("Basic (base64LoginString())", forHTTPHeaderField: "Authorization")
    request.setValue("multipart/form-data; boundary=(boundary)", forHTTPHeaderField: "Content-Type")

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

    return request
}

func createBodyWithParameters(json: [String:AnyObject], paths: [String]?, boundary: String) -> NSData {
    let body = NSMutableData()
    let key = "userDTO"

    body.appendString("--(boundary)rn")
    body.appendString("Content-Type: application/json")
    body.appendString("Content-Disposition: form-data; name="(key)"rnrn")
    var requestBody = NSData()

    do {
        requestBody = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions(rawValue:0))
    } catch (let e) {
        print(e)
    }
    body.appendData(requestBody)
    //body.appendString("(json)rn")

    if paths != nil {
        for path in paths! {
            let url = NSURL(fileURLWithPath: path)
            let data = NSData(contentsOfURL: url)!
            let mimetype = mimeTypeForPath(path)
            let fileName = "sample-image23.png"
            let date = "Fri, 22 Jan 2016 04:56:48 GMT"
            let name = "file"

            body.appendString("--(boundary)rn")
            body.appendString("Content-Type: (mimetype)rnrn")
            body.appendString("Content-Disposition: form-data; filename="(fileName)"; modification-date="(date)"; size=3308; name="(name)"rn")
            body.appendData(data)
            body.appendString("rn")
        }
    }

    body.appendString("--(boundary)--rn")
    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";
}

Также расширение

extension NSMutableData {

    func appendString(string: String) {
        let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
        appendData(data!)
    }
}

Я думаю, что делаю какую-то ошибку в формате json. Кто-нибудь может помочь? Спасибо!

2 3

2 ответа:

Похоже, загрузка изображения-это не ваша проблема , насколько я вижу, это удалось. Вы должны понимать, что загрузка изображения не имеет ничего общего с JSON. Скорее всего, вы ищете ответ в ожидаемом формате (JSON). Таким образом, если вам требуется получить ответ, тело которого является JSON, вы должны явно заявить об этом, установив соответствующий заголовок Accept. Например:

Accept: application/json

И в коде:

request.setValue("application/json", forHTTPHeaderField: "Accept")

Когда вы получаете ответ, вы также должны сначала проверить код состояния ответа, а затем заголовок Content-Type (соответственно, свойство response' MIMEType), который должен соответствовать тому, что вы ожидаете: application/json.

Если тип контента не соответствует вашим ожиданиям, вы можете попробовать дополнительные "сериализаторы ответов" - каждый из них подходит для анализа других типов контента, например text/plain и т. д.- как вам будет угодно.

Редактировать:

Сервер ответил намеком, что вторая часть составного запроса является бесформенный. Взглянув на то, как он составлен:

        body.appendString("--\(boundary)\r\n")
        body.appendString("Content-Type: \(mimetype)\r\n\r\n")
        body.appendString("Content-Disposition: form-data; filename='sample-image23.png'; modification-date='Fri, 22 Jan 2016 04:56:48 GMT'; size=3308; name='file'\r\n")
        body.appendData(data)
        body.appendString("\r\n")

Теперь, присмотревшись, мы можем увидеть, что второй заголовок Content-Type будет разделен двумя CRLF - но за этим следует еще один заголовок. Заголовки должны быть разделены только одним CRLF.

Тогда, последний заголовок должен быть разделен двумя CRLF.

Предложенное исправление:

        body.appendString("--\(boundary)\r\n")
        body.appendString("Content-Disposition: form-data; filename='sample-image23.png'; modification-date='Fri, 22 Jan 2016 04:56:48 GMT'; size=3308; name='file'\r\n")
        body.appendString("Content-Type: \(mimetype)\r\n\r\n")
        body.appendData(data)
        body.appendString("\r\n")

(правка: удалено неверное описание)

Правка 2:

В этих строках, над этой, также отсутствует CRLF:

let key = "userDTO"

body.appendString("--\(boundary)\r\n")
body.appendString("Content-Type: application/json")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")

Вы видите проблему? Content-Type не имеет конца CRLF!

Смотрите также: NSURLRequest загрузить несколько файлов

Этот фрагмент кода поможет вам загрузить файлUIImage в веб-сервис с помощью методаPOST .

func uploadImageOne(){
    var imageData = UIImagePNGRepresentation(exampleImageView.image)

    if imageData != nil{
        var request = NSMutableURLRequest(URL: NSURL(string:"Your URL")!)
        var session = NSURLSession.sharedSession()

        request.HTTPMethod = "POST"

        var boundary = NSString(format: "---------------------------14737809831466499882746641449")
        var contentType = NSString(format: "multipart/form-data; boundary=%@",boundary)
      //  println("Content Type \(contentType)")
        request.addValue(contentType, forHTTPHeaderField: "Content-Type")

        var body = NSMutableData.alloc()

        // Title
         body.appendData(NSString(format: "\r\n--%@\r\n",boundary).dataUsingEncoding(NSUTF8StringEncoding)!)
        body.appendData(NSString(format:"Content-Disposition: form-data; name=\"title\"\r\n\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
        body.appendData("Hello World".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)

        // Image
        body.appendData(NSString(format: "\r\n--%@\r\n", boundary).dataUsingEncoding(NSUTF8StringEncoding)!)
        body.appendData(NSString(format:"Content-Disposition: form-data; name=\"profile_img\"; filename=\"img.jpg\"\\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
        body.appendData(NSString(format: "Content-Type: application/octet-stream\r\n\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
        body.appendData(imageData)
        body.appendData(NSString(format: "\r\n--%@\r\n", boundary).dataUsingEncoding(NSUTF8StringEncoding)!)



        request.HTTPBody = body


        var returnData = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil)

        var returnString = NSString(data: returnData!, encoding: NSUTF8StringEncoding)

        println("returnString \(returnString)")

    }


}