2015-04-30 13 views
8

[CẢNH BÁO]
Như tôi nhìn thấy rằng câu hỏi này là nhận được chú ý hơn nó nên, Tôi muốn nói với bạn không nên sử dụng bất kỳ mã sau.
Vào thời điểm tôi hỏi câu hỏi, Swift đã ít hơn một năm, đang chuyển động nhanh, hầu hết các thư viện đều không thân thiện với Swift và không ổn định. Tôi khuyên bạn nên thử sử dụng Alamofire hoặc một thư viện khác cho loại nhiệm vụ đó. Nhưng đừng tự làm. [/ WARNING]tải lên một hình ảnh và thông số với multipart/form-data trong Swift

Tôi muốn tải hình ảnh lên điểm cuối Drupal.

Vấn đề tôi gặp phải là tôi nhận được phản hồi HTTP 200 OK với loại nội dung văn bản/html. Trong phản hồi HTML, có một thông báo rõ ràng rằng nút đã được tạo chính xác. Nhưng ở phía máy chủ, hình ảnh không được liên kết với nút.

Ngoài ra tôi không mong đợi văn bản/html nhưng ứng dụng/json khi tôi chỉ định nó trong tiêu đề Chấp nhận.

Nó đã hoạt động trong ứng dụng Android sử dụng Mẫu phần còn lại của Android. Đây là đoạn mã để tham khảo:

String url = getUrl("node/{info_id}/attach_file"); 

HttpHeaders headers = new HttpHeaders(); 
headers.setContentType(MediaType.MULTIPART_FORM_DATA); 

if (user.isLoggedIn()) { 
    headers.add(user.getSessionName(), user.getSessionId()); 
    headers.add("X-CSRF-Token", user.getToken()); 
    headers.add("Cookie", user.getSessionName() + "=" + user.getSessionId()); 
} 

MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>(); 

parts.add("files[field_mobileinfo_image]", 
     new FileSystemResource(info.getImageUri())); 
parts.add("field_name", "field_mobileinfo_image"); 

HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(parts, headers); 
return getRestTemplate().exchange(url, HttpMethod.POST, request, Void.class, info.getId()).getBody(); 

Tôi biết tôi không kiểm tra phản ứng trong Android (Void.class) nhưng tất cả mọi thứ hoạt động tốt và hình ảnh được gắn vào nút ở phía máy chủ.

Bây giờ trên iOS trong Swift, tôi đã thử nhiều thứ.

Với AFNetworking:

func upload(mobileInfo: MobileInfo) { 
    let user = userService.load() 
    let url = Config.buildUrl("") 

    let manager = AFHTTPRequestOperationManager(baseURL: NSURL(string:url)!) 
    let serializer = AFHTTPRequestSerializer() 
    serializer.setValue(user.sessionId, forHTTPHeaderField: user.sessionName) 
    serializer.setValue(user.token, forHTTPHeaderField: "X-CSRF-Token") 
    serializer.setValue("\(user.sessionName)=\(user.sessionId)", forHTTPHeaderField: "Cookie") 
    manager.requestSerializer = serializer 

    manager.responseSerializer.acceptableContentTypes.removeAll(keepCapacity: false) 
    manager.responseSerializer.acceptableContentTypes.insert("application/json") 

    let imageData = UIImageJPEGRepresentation(mobileInfo.image, 0.3)  
    manager.POST("/node/\(mobileInfo.id)/attach_file", parameters: nil, constructingBodyWithBlock: { (formData) -> Void in 
     formData.appendPartWithFileData(
      imageData, 
      name: "files[field_mobileinfo_image]", 
      fileName: "field_mobileinfo_image", 
      mimeType: "image/jpeg") 
     formData.appendPartWithFormData("field_mobileinfo_image".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true), name: "field_name") 
    }, 
    success: { (operation, data) -> Void in 
     println(data) 
    }) { (operation, error) -> Void in 
     println(error) 
    } 
} 

thủ với thông tin nắm lấy từ câu hỏi stackoverflow khác:

func upload2(mobileInfo: MobileInfo) { 
    let user = userService.load() 
    let imageData = UIImageJPEGRepresentation(mobileInfo.image, 0.3) 
    let url = NSURL(string:Config.buildUrl("/node/\(mobileInfo.id)/attach_file"))! 
    println(url) 
    var request = NSMutableURLRequest(URL: url) 
    var session = NSURLSession.sharedSession() 
    request.HTTPMethod = "POST" 
    var boundary = "---------------------------14737809831466499882746641449" 
    var contentType = "multipart/form-data; boundary=\(boundary)" 
    println(contentType) 
    request.addValue(contentType, forHTTPHeaderField: "Content-Type") 
    request.addValue("application/json", forHTTPHeaderField: "Accept") 
    request.addValue("\(user.sessionName)=\(user.sessionId)", forHTTPHeaderField: "Cookie") 
    request.addValue(user.sessionId, forHTTPHeaderField: user.sessionName) 
    request.addValue(user.token, forHTTPHeaderField: "X-CSRF-Token") 

    println(request.allHTTPHeaderFields) 

    var body = NSMutableData() 

    body.appendData("\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    body.appendData("Content-Disposition: form-data; name=\"field_name\"\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    body.appendData("field_mobileinfo_image".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!) 

    body.appendData("\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    body.appendData("Content-Disposition: form-data; name=\"files[field_mobileinfo_image]\"; filename=\"img.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    body.appendData("Content-Type: application/octet-stream\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    body.appendData(imageData) 
    body.appendData("\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 


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

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

    println("returnString \(returnString)") 
} 

Với SRWebClient:

func upload3(mobileInfo: MobileInfo) { 
    let user = userService.load() 
    let imageData:NSData = NSData(data: UIImageJPEGRepresentation(mobileInfo.image, 0.3)) 
    SRWebClient.POST("http://master.test.lesfrontaliers.lu/node/\(mobileInfo.id)/attach_file") 
     .headers(["Accept": "application/json", 
      user.sessionName: user.sessionId, 
      "X-CSRF-Token": user.token, 
      "Cookie": "\(user.sessionName)=\(user.sessionId)"]) 
     .data(imageData, fieldName:"files[field_mobileinfo_image]", data:["field_name":"field_mobileinfo_image"]) 
     .send({ (response: AnyObject!, status: Int) -> Void in 
      println(status) 
      println(response) 
     },failure:{(error:NSError!) -> Void in 
      println(error) 
     }) 
} 

Hãy cứu tôi! ;-) Tôi đã thử rất nhiều điều để làm cho nó hoạt động mà tôi không thể nhìn thấy nữa nếu tôi làm điều gì đó sai trái. Nó có vẻ ok cho tôi. Sự khác biệt duy nhất tôi có thể thấy là tôi không lưu trữ hình ảnh trên hệ thống tập tin nhưng trực tiếp gửi dữ liệu nhị phân mà là cùng một điều ở cuối.

Dưới đây là một hình ảnh của yêu cầu tạo ra trong Postman (làm việc và nhận json)

Postman

[EDIT] Nếu nó có thể giúp ai đó ở đây là mã chính xác của phần sai của trên tay yêu cầu:

var body = NSMutableData() 

body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
body.appendData("Content-Disposition: form-data; name=\"field_name\"\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
body.appendData("field_mobileinfo_image\r\n".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!) 

body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
body.appendData("Content-Disposition: form-data; name=\"files[field_mobileinfo_image]\"; filename=\"img.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
body.appendData("Content-Type: image/jpeg\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
body.appendData(imageData) 
body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 

body.appendData("--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 

request.HTTPBody = body 
+0

như thế nào là điều này được thực hiện khi tôi cần phải gửi lên các thông số bài là tốt? http://stackoverflow.com/questions/30006290/uploading-image-in-swift-with-multiple-parameters – Tyler

+0

Tại sao bạn chỉ định 'image.jpeg' nếu tệp của bạn có phần mở rộng' png'? –

+0

Ngoài ra, tôi luôn tự hỏi hai bổ sung, dẫn dấu gạch ngang trước chuỗi ranh giới ('--') là gì. –

Trả lời

2

không biết nếu điều này sẽ làm việc cho những gì bạn đang cố gắng làm nhưng chúng tôi sử dụng để tải lên hình ảnh, sự khác biệt chính là sử dụng filenameContent-type:

[self appendBody:body data:[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\".jpg\"\r\n", key]]; 

[self appendBody:body data:@"Content-Type: image/jpeg\r\n\r\n"]; 
[body appendData:imageData]; 
+1

OMG. Cảm ơn bạn rất nhiều. Bạn đặt tôi đi đúng hướng. Tôi không biết tại sao tôi đã làm rất nhiều crap với các "hướng dẫn" yêu cầu, nhưng nếu bạn nhìn vào câu hỏi của tôi nó là hoàn toàn sai (không có ranh giới cuối cùng vv) và trên đó ... cơ thể không được đặt trên yêu cầu . Thêm hình ảnh Content-Type/jpeg cuối cùng đã cho tôi một lỗi từ máy chủ thay vì sai HTTP 200. Điều làm phiền tôi là AFNetworking và SRWebClient không hoạt động mặc dù chúng được sử dụng nhiều. – florian

+0

Tuyệt vời, vui vì bạn đã làm việc đó! Yeah, mạng luôn có vẻ đau đớn hơn. – rmp

1

Đối với bất kỳ nhanh chóng 2,0 JSON yêu cầu và mã PHP: - (Manual)

let imageData = UIImageJPEGRepresentation(userImage, 0.3) 
    let url:NSURL = NSURL(string: serverURL!)! // Give ur request URL 
    let request = NSMutableURLRequest(URL: url) 
    request.HTTPMethod = "POST" 
    let boundary = "---------------------------14737809831466499882746641449" 
    let contentType = "multipart/form-data; boundary=\(boundary)" 
    request.addValue(contentType, forHTTPHeaderField: "Content-Type") 
    let body = NSMutableData() 
    body.appendData("--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    body.appendData("Content-Disposition: form-data; name=\"userfile\"; filename=\"img.jpg\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    body.appendData("Content-Type: image/jpeg\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    body.appendData("Content-Transfer-Encoding: binary\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    body.appendData(imageData!) 
    body.appendData("\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    body.appendData("--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 
    request.HTTPBody = body 

PHP Code: -

<?php 

//http://192.168.1.154/Contact/uploadImgwebservice.php 

//print the username and password using php 

echo $_POST[‘username’]; 

echo $_POST[‘password’]; 

//upload your file 

$uploaddir = ‘./uploads/’; 

$file = basename($_FILES[‘userfile’][‘name’]); 

$uploadfile = $uploaddir . $file; 

if (move_uploaded_file($_FILES[‘userfile’][‘tmp_name’], $uploadfile)) { 

    echo “http://192.168.1.154/Contact/uploads/{$file}”; 

} 

?> 
Các vấn đề liên quan