2017-02-17 2 views
1

Я работаю над проектом, в котором я хотел бы выбрать изображение, а затем загрузить его на сервер. Я могу нажать кнопку загрузки изображения, выбрать изображение и изменить изображение в симуляторе iOS, но загрузка не удалась. Когда я включаю print(request) после инструкции request.httpBody = creatBodyWithParams(), это показывает, что исходный url не изменился. Я использую XAMPP для настройки виртуального сервера и php для связи с ним.Загрузка изображения на сервер с быстрым (php, json, swift)

Мой код:

// upload image button clicked 
@IBAction func edit_click(_ sender: Any) { 

    // select image 
    let picker = UIImagePickerController() 
    picker.delegate = self 

    //picker.sourceType = UIImagePickerControllerSourceType.photoLibrary 
    picker.allowsEditing = true 
    self.present(picker, animated: true, completion: nil) 
} 

// selected image 
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { 
    avaImg.image = info[UIImagePickerControllerEditedImage] as? UIImage 
    self.dismiss(animated: true, completion: nil) 

    // call function of uploading image file to server 
    uploadImage() 
} 

// create body of HTTP request to upload image file 
func createBodyWithParams(parameters: [String : String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData { 

    let body = NSMutableData(); 

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

    let filename = "image.jpg" 

    let mimetype = "image/jpg" 

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

    body.appendString(string: "--\(boundary)--\r\n") 

    return body 
} 

// upload image to server 
func uploadImage() { 

    let id = user!["id"] as! String 

    let address = URL(string: "http://localhost/project/uploadImage.php")! 
    var request = URLRequest(url: address) 
    request.httpMethod = "POST" 
    let param = ["id" : id] 

    let boundary = "Boundary-\(NSUUID().uuidString)" 

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

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

    if imageData == nil { 
     return 
    } 

    request.httpBody = createBodyWithParams(parameters: param, filePathKey: "file", imageDataKey: imageData! as NSData, boundary: boundary) as Data 

    // launch session 
    let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in 

     // get main queue to communicate back to user 
     DispatchQueue.main.async { 

      if error == nil { 

       do { 

        let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary 

        guard let parseJSON = json else { 

         print("error while parsing") 
         return 

        } 

        print(parseJSON) 

       } catch { 

        print("Caught an error: \(error)") 

       } 

      } else { 

       print(error) 

      } 
     } 
    }) 

    task.resume() 

} 

С следующим расширением:

// creating protocol of appending string to var of type data 
extension NSMutableData { 

    appendString(string : String) { 

     let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true) 
     append(data!) 

    } 
} 

Я проконсультировался на следующих страницах помощи и попытался изменить мой код, чтобы отразить различия в подходах, но я левая стукнула головой о стену.

Uploading image with other parameters in SWIFT

Upload image with parameters in Swift

http://www.kaleidosblog.com/how-to-upload-images-using-swift-2-send-multipart-post-request

EDIT 1:

Забыли сообщение об ошибке (Dur): Caught an error: Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}

Ошибка возникающую где-то в do заявлении. Я думаю, что что-то происходит с request, потому что тестирование http://localhost/project/uploadImage.php в браузере возвращает массив {"message":"Missing required information"}

EDIT 2: PHP код

uploadImage.php

<?php 

// report all errors except E_NOTICE 
error_reporting(E_ALL & ~E_NOTICE); 

// Part 1: Upload File 
// Step 1: check data passed to this php file 
if (empty($_REQUEST["id"])) { 

    $returnArray["message"] = "Missing required information"; 
    print json_encode($returnArray); 
    return; 
} 

// request user id 
$id = htmlentities($_REQUEST["id"]); 

// step 2: create a folder for user with id as folder name 
$folder = "/Applications/XAMPP/xamppfiles/htdocs/project/image/" . $id; 

// if folder doesn't exist 
if (!file_exists($folder)) { 

    mkdir($folder, 0777, true); 

} 

// step 3: move uploaded file 
$folder = $folder . "/" . basename($_FILES["file"]["name"]); 

if (move_uploaded_file($_FILES["file"]["tempname"], $folder)) { 
    $returnArray["status"] = "200"; 
    $returnArray["message"] = "The file has been uploaded successfully."; 
} else { 
    $returnArray["status"] = "300"; 
    $returnArray["message"] = "Error while uploading."; 
} 


// Part 2: Updating image path 
// build secure connection 

$file = parse_ini_file("../../../project.ini"); 

// store variable information from ini file in php as variables 
$host = trim($file["dbhost"]); 
$user = trim($file["dbuser"]); 
$pass = trim($file["dbpass"]); 
$name = trim($file["dbname"]); 

// include access.php to call connect function from access.php file 
require ("secure/access.php"); 
$access = new access($host, $user, $pass, $name); 
$access->connect(); 

// STEP 5: save path to uploaded file in database 
$path = "http://localhost/project/image/" . $id . "/ava.jpg"; 
$access->updateImagePath($path, $id); 

// STEP 6: get new user information after updating 
$user = $access->selectUserViaID($id); 

$returnArray["id"] = $user["id"]; 
$returnArray["username"] = $user["username"]; 
$returnArray["fullname"] = $user["fullname"]; 
$returnArray["email"] = $user["email"]; 
$returnArray["image"] = $user["image"]; 

// Step 7. Close Connection 
$access->disconnect(); 

// Step 8. feedback array to app 
echo json_encode($returnArray); 

?> 
+0

Что отображается ошибка при печати в окне консоли? – Pierce

+0

Что вы получите, если вы поместите 'print (String (data: data !, encoding: .utf8))' перед 'DispatchQueue.main.async'? – OOPer

+0

@OOPer Когда я добавляю 'печати (String (данные: данные !, кодирования: .utf8))' 'Перед DispatchQueue.main.async' я получаю следующее перед сообщением об ошибке я включил в основном посте: '
Примечание: Undefined индекс: tempname в /Applications/XAMPP/xamppfiles/htdocs/project/uploadImage.php на линии
{ "статус": "300", "сообщение":" Error при загрузке. "," id ":" 98 "," username ":" username "," fullname ":" full name "," email ":" ***** @ me.com "," image ": "http: \/\/localhost \/project \/image \/98 \/ava, jpg"} ' – nsmedira

ответ

0

С помощью @OOper в комментариях I смог отслеживать ошибку в синтаксической ошибке в функции, вызванной моим основным файлом uploadImage.php (см. основной пост), а также с использованием "tempname", когда я должен был использовать «tmp_name».

Смежные вопросы