iOS Swift 5 - Загрузить файл с сервера, вызвав функцию PHP - PullRequest
1 голос
/ 20 января 2020

Я пытаюсь загрузить файл (в этом случае я пытаюсь с изображением, но мне нужно было бы иметь возможность загрузить любой тип файла, особенно видеофайл) на мой сервер.

Это мой PHP код, и он отлично работает на стороне сервера:

<?php include '_config.php';

if ($_FILES["file"]["error"] > 0) {
    echo "Error: " .$_FILES["file"]["error"]. "<br>";

} else {
    // Check file size
    if ($_FILES["file"]["size"] > 20485760) { // 20 MB
        echo "ERROR: Your file is larger than 20 MB. Please upload a smaller one.";    
    } else { uploadImage(); }

}// ./ If


// UPLOAD IMAGE ------------------------------------------
function uploadImage() {
    // generate a unique random string
    $randomStr = generateRandomString();
    $filePath = "uploads/".$randomStr;

    // upload image into the 'uploads' folder
    move_uploaded_file($_FILES['file']['tmp_name'], $filePath);

    // echo the link of the uploaded image
    echo $filePath;
}

// GENERATE A RANDOM STRING ---------------------------------------
function generateRandomString() {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i<20; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString."_".$_POST['fileName'];
}
?>

Это моя функция Swift 5:

func uploadFile(_ aImage:UIImage, maxWidth:CGFloat, completion: @escaping (_ fileURL:String?) -> Void) {
        showHUD()
        let image = scaleImageToMaxWidth(image: aImage, newWidth: maxWidth)

        // Generate a random filename
        var filename = ""
        for _ in 0..<20 {
            let randomChar = Int(arc4random() % UInt32(charsForRand.count))
            filename += charsForRand[randomChar]
        }
        filename += "__image.jpg"
        print("FILENAME: \(filename)")

        let boundary = UUID().uuidString
        let fieldName = "reqtype"
        let fieldValue = "fileupload"
        let fieldName2 = "userhash"
        let fieldValue2 = "caa3dce4fcb36cfdf9258ad9c"

        let config = URLSessionConfiguration.default
        let session = URLSession(configuration: config)
        var urlRequest = URLRequest(url: URL(string: DATABASE_PATH + "upload-file.php")!)
        urlRequest.httpMethod = "POST"
        urlRequest.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

        var data = Data()
        data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
        data.append("Content-Disposition: form-data; name=\"\(fieldName)\"\r\n\r\n".data(using: .utf8)!)
        data.append("\(fieldValue)".data(using: .utf8)!)
        data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
        data.append("Content-Disposition: form-data; name=\"\(fieldName2)\"\r\n\r\n".data(using: .utf8)!)
        data.append("\(fieldValue2)".data(using: .utf8)!)
        data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
        data.append("Content-Disposition: form-data; name=\"fileToUpload\"; fileName=\"\(filename)\"\r\n".data(using: .utf8)!)
        data.append("Content-Type: image/png\r\n\r\n".data(using: .utf8)!)

        data.append(image.jpegData(compressionQuality: 1.0)!)

        data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)

        // Send a POST request to the URL, with the data we created earlier
        session.uploadTask(with: urlRequest, from: data, completionHandler: { responseData, response, error in
            if error != nil { print("\(error!.localizedDescription)") }

            guard let responseData = responseData else {
                DispatchQueue.main.async {
                    self.simpleAlert("Something went wrong while uploading, try again.")
                }
                completion(nil)
                return
            }

            if let response = String(data: responseData, encoding: .utf8) {
                completion("\(DATABASE_PATH)\(response)")
                print("UPLOAD URL: \(DATABASE_PATH)\(response)")
            }
        }).resume()
    }

Я вызываю эту функцию в моем ViewController выглядит следующим образом:

uploadFile(UIImage(named: "default_avatar")!, maxWidth: 300) { (fileURL) in
    if fileURL != nil {
         print("FILE URL: \(fileURL!)")
     }
}

Но вот что я получаю в консоли Xcode:

FILE URL: https://example.com/uploads/8iWQOrwr0wgNDor8XNhX_
UPLOAD URL: https://example.com/uploads/8iWQOrwr0wgNDor8XNhX_

Это означает, что моя функция не добавляет "__ image.jpg" строка для переменной filename, и она также не загружает мое изображение в папку загрузки на моем сервере.

Что я делаю не так? Если я вызываю мой PHP сценарий из формы с вводом типа file , он работает как чудо. Поэтому мой сценарий PHP в порядке, поэтому я, безусловно, что-то делаю неправильно Функция Swift.

1 Ответ

0 голосов
/ 11 февраля 2020

Я нашел решение, вот моя отредактированная функция Swift 5, которая теперь также может принимать mp4 видеофайлы, а не только jpg или png изображения:

func uploadFile(fileData:Data, fileName:String , completion: @escaping (_ fileURL:String?, _ error:String?) -> Void) {
        print("FILENAME: \(fileName)")

        let boundary: String = "------VohpleBoundary4QuqLuM1cE5lMwCy"
        let contentType: String = "multipart/form-data; boundary=\(boundary)"
        let request = NSMutableURLRequest()
        request.url = URL(string: DATABASE_PATH + "upload-file.php")
        request.httpShouldHandleCookies = false
        request.timeoutInterval = 60
        request.httpMethod = "POST"
        request.setValue(contentType, forHTTPHeaderField: "Content-Type")
        let body = NSMutableData()
        body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
        body.append("Content-Disposition: form-data; name=\"fileName\"\r\n\r\n".data(using: String.Encoding.utf8)!)
        body.append("\(fileName)\r\n".data(using: String.Encoding.utf8)!)

        body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
        body.append("Content-Disposition: form-data; name=\"file\"; filename=\"file\"\r\n".data(using: String.Encoding.utf8)!)

        // File is an image
        if fileName.hasSuffix(".jpg") {
            body.append("Content-Type:image/png\r\n\r\n".data(using: String.Encoding.utf8)!)
        // File is a video
        } else if fileName.hasSuffix(".mp4") {
            body.append("Content-Type:video/mp4\r\n\r\n".data(using: String.Encoding.utf8)!)
        }

        body.append(fileData)
        body.append("\r\n".data(using: String.Encoding.utf8)!)


        body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
        request.httpBody = body as Data
        let session = URLSession.shared
        let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
            guard let _:Data = data as Data?, let _:URLResponse = response, error == nil else {
                DispatchQueue.main.async { completion(nil, error!.localizedDescription) }
                return
            }
            if let response = String(data: data!, encoding: String.Encoding(rawValue: String.Encoding.utf8.rawValue)) {
                print("XSUploadFile -> RESPONSE: " + DATABASE_PATH + response)
                DispatchQueue.main.async { completion(DATABASE_PATH + response, nil) }

            // NO response
            } else { DispatchQueue.main.async { completion(nil, E_401) } }// ./ If response
        }; task.resume()
    }

Вот как Я использую эту функцию:

let imageData = UIImage(named: "my_img")!.jpegData(compressionQuality: 1)
uploadFile(fileData: imageData!, fileName: "image.jpg") { (fileURL, e) in
   if e == nil {
       print("FILE URL: " + fileURL!)
}}

Это работает на 100%.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...