EDIT: Хорошо, я просто установил заголовок типа контента для multipart / form-data без разницы. Мой первоначальный вопрос ниже:
Это мой первый вопрос о переполнении стека, я надеюсь, что все правильно.
Я изучаю Objective-C, недавно завершив онлайн-версию курса Стэнфорда. Я ничего не знаю о php и html. Сценарий php и используемый мной html в основном копируются с учебника. Obj-C имеет больше смысла для меня.
Проблема:
У меня есть php-скрипт. Он загружает файл изображения. Он корректно работает при вызове из html-файла в той же папке на сервере. Я пытаюсь заставить тот же скрипт работать, когда он вызывается из моего obj-c. Кажется, что он запускается, он возвращает 200, obj-c вызывает php, но в онлайновой папке не появляется файл.
Похоже, об этом в Интернете очень мало, поскольку он был введен только в ios7. Никаких примеров, которые я нашел, касаются загрузки файлов, все они имеют дело с загрузкой и просто говорят, что загрузка похожа. То, что я сделал, похоже, удовлетворяет любым учебникам, которые я нашел.
Я знаю, что:
Что может быть важно :
Вот цель C
- (void) uploadFile: (NSURL*) localURL toRemoteURL: (NSURL*) phpScriptURL { NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]]; NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:phpScriptURL]; [request setHTTPMethod:@"POST"]; NSURLSessionUploadTask* uploadTask = [defaultSession uploadTaskWithRequest:request fromFile:localURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){ if (error == nil) { NSLog(@"NSURLresponse =%@", [response description]); // do something !!! } else { //handle error } [defaultSession invalidateAndCancel]; }]; self.imageView.image = [UIImage imageWithContentsOfFile:localURL.path]; //to confirm localURL is correct [uploadTask resume]; }
и вот PHP-скрипт, который находится на сервере
<?php $file = 'log.txt'; $current = file_get_contents($file); $current .= $_FILES["file"]["name"]." is being uploaded. "; //should write the name of the file to log.txt file_put_contents($file, $current); ini_set('display_errors',1); error_reporting(E_ALL); $allowedExts = array("gif", "jpeg", "jpg", "png"); $temp = explode(".", $_FILES["file"]["name"]); $extension = end($temp); if ((($_FILES["file"]["type"] == "image/gif") || ($_FILES["file"]["type"] == "image/jpeg") || ($_FILES["file"]["type"] == "image/jpg") || ($_FILES["file"]["type"] == "image/pjpeg") || ($_FILES["file"]["type"] == "image/x-png") || ($_FILES["file"]["type"] == "image/png")) //&& ($_FILES["file"]["size"] < 100000) //commented out for error checking && in_array($extension, $allowedExts)) { if ($_FILES["file"]["error"] > 0) { echo "Return Code: " . $_FILES["file"]["error"] . "<br>"; } else { echo "Upload: " . $_FILES["file"]["name"] . "<br>"; echo "Type: " . $_FILES["file"]["type"] . "<br>"; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " kB<br>"; echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br>"; if (file_exists("upload/" . $_FILES["file"]["name"])) { echo $_FILES["file"]["name"] . " already exists. "; } else { if (move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"])) { echo "Stored in: " . "upload/" . $_FILES["file"]["name"]; } else { echo "Error saving to: " . "upload/" . $_FILES["file"]["name"]; } } } } else { echo "Invalid file"; } ?>
и вот html-файл, который работает как ожидается при вызове того же скрипта
<html> <body> <form action="ios_upload.php" method="post" enctype="multipart/form-data"> <label for="file">Filename:</label> <input type="file" name="file" id="file"><br> <input type="submit" name="submit" value="Submit"> </form> </body>
Я просто ответил на этот же вопрос: https://stackoverflow.com/a/28269901/4518324
В принципе, файл загружается на сервер в тело запроса как двоичный.
Чтобы сохранить этот файл в PHP, вы можете просто получить тело запроса и сохранить его в файле.
Ваш код должен выглядеть примерно так:
Код Objective-C:
- (void) uploadFile: (NSURL*) localURL toRemoteURL: (NSURL*) phpScriptURL { // Create the Request NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:phpScriptURL]; [request setHTTPMethod:@"POST"]; // Configure the NSURL Session NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.upload"]; [sessionConfig setHTTPMaximumConnectionsPerHost: 1]; NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:nil]; NSURLSessionUploadTask* uploadTask = [defaultSession uploadTaskWithRequest:request fromFile:localURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){ if (error == nil) { NSLog(@"NSURLresponse =%@", [response description]); // do something !!! } else { //handle error } [defaultSession invalidateAndCancel]; }]; self.imageView.image = [UIImage imageWithContentsOfFile:localURL.path]; //to confirm localURL is correct [uploadTask resume]; }
Код PHP:
<?php // Get the Request body $request_body = @file_get_contents('php://input'); // Get some information on the file $file_info = new finfo(FILEINFO_MIME); // Extract the mime type $mime_type = $file_info->buffer($request_body); // Logic to deal with the type returned switch($mime_type) { case "image/gif; charset=binary": // Create filepath $file = "upload/image.gif"; // Write the request body to file file_put_contents($file, $request_body); break; case "image/png; charset=binary": // Create filepath $file = "upload/image.png"; // Write the request body to file file_put_contents($file, $request_body); break; default: // Handle wrong file type here echo $mime_type; } ?>
Я написал пример кода для записи звука и загрузки его на сервер здесь: https://github.com/gingofthesouth/Audio-Recording-Playback-and-Upload
Он показывает код с сохранением на устройстве iOS, загрузку и сохранение на сервер.
Надеюсь, это поможет.