Почему NSURLSession uploadTaskWithRequest: fromData: не удается загрузить на php-сервер?

PHP-код работает нормально. Я загрузил файлы из html-формы на тот же сервер. Загруженные файлы имеют размер от 40 КБ до 2,0 МБ, поэтому это не размер. Загрузка файлов активирована на сервере с PHP 5.3.

Я нашел много сообщений, таких как этот (пока без ответа): https://stackoverflow.com/questions/19710388/using-nsurlsession-to-upload-an-image.

Здесь используется uploadTaskWithRequest:fromFile: вместо fromData:NSURLSession убедитесь, что загрузка работает

Это NSURLSessionDataTask вместо uploadTaskWithRequest:Нет данных, полученных с NSURLSession

И некоторые сообщения, в которых говорится, что uploadTaskWithRequest:fromData: просто не работает: NSURLSession: upload ресурсы с фоновой передачей асинхронная загрузка с NSURLSession не будет работать, но синхронная NSURLConnection будет работать и Загрузить изображение с iOS на PHP

Я сделал приложение таким, что оно возвращает код HTTP, и я получаю код 200. В файле error_log сервера после загрузки ничего нет. Вроде все работает нормально, но что бы ни случилось, файл не записывается на сервер. Любые идеи, что еще я могу попытаться выяснить, что происходит не так?

Вот php-код:

<?php
$file='';
$uploaddir='';

////////////////
echo 'file count=', count($_FILES),"\n";
var_dump($_FILES);
echo "\n";
////////////////

if(isset($_FILES['userfile']['name'])){
      $uploaddir = './photos/'; //Uploading to same directory as PHP file
      $file = basename($_FILES['userfile']['name']);
      echo "file is set";
      $uploadFile = $file;
      $randomNumber = rand(0, 99999); 
      $newName = $uploaddir . $uploadFile;
        if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
            echo "Temp file uploaded. \r\n";
        } else {
            echo "Temp file not uploaded. \r\n";
        }
   if (move_uploaded_file($_FILES['userfile']['tmp_name'], $newName)) {
         $postsize = ini_get('post_max_size'); //Not necessary, I was using these
         $canupload = ini_get('file_uploads'); //server variables to see what was 
         $tempdir = ini_get('upload_tmp_dir'); //going wrong.
         $maxsize = ini_get('upload_max_filesize');
         echo "\r\n" .  $_FILES['userfile']['size'] . "\r\n" . $_FILES['userfile']['type'] ;
    }
}
?>

и вот код iOS:

- (void)uploadImage:(UIImage*)image {

    // 0 Define URL
    NSData *imageData = UIImageJPEGRepresentation(image, 0.6);
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://www.myserver.com/app/photos/uploadPhoto.php"]];
    NSString *boundary = @"0xKhTmLbOuNdArY";
    NSString *filename = [NSString stringWithFormat:@"someName.jpg"];
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    [request setHTTPMethod:@"POST"];
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSURLSession *upLoadSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];

    // 4 Create object to put content into...
    NSMutableData *body = [NSMutableData data];
    [request addValue:contentType forHTTPHeaderField:@"Content-Type"];
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\" filename=\"%@\"\r\n",filename]] dataUsingEncoding:NSUTF8StringEncoding]];
    //[body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

    [body appendData:[NSData dataWithData:imageData]];
    [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];


    //Not used with this:https://stackoverflow.com/questions/20893171/asynchronous-upload-with-nsurlsession-will-not-work-but-synchronous-nsurlconnect/20896632?noredirect=1#comment39074802_20896632
    //[request setHTTPBody:body];


    __block NSString *stringForText = @"Hola";
    ///////////////////////////////////////////////////
    // 3
    self.uploadTask = [upLoadSession uploadTaskWithRequest:request fromData:body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        // ...
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response;
        int errorCode = httpResponse.statusCode;
        NSString *errorStatus = [NSString stringWithFormat:@"%d",errorCode];

        NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSString *totalResponse = [errorStatus stringByAppendingString:responseString];

        stringForText = totalResponse;
        [self updateView:stringForText];
        //UIAlertView *alertme = [[UIAlertView alloc] initWithTitle:@"error" message:totalResponse delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
        //[alertme show];
        // 4
        self.uploadView.hidden = NO;
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    }];


    // 5
    [_uploadTask resume];
}

-(void)updateView:(NSString*)texto{
    dispatch_sync(dispatch_get_main_queue(), ^{
        self.myTextView.text = texto;
    });

}

У меня есть 777 разрешений на эту папку. Как я уже сказал, мне удалось загрузить и, таким образом, записать в эту папку из того же php-скрипта через html-форму.

TotalResponse равен 200 для кода ошибки http и count=0, а также array(0) {} для дампа php.

Вот изображение ответа сервера прямо в приложении:введите здесь описание изображения

Я добавил эти строки после повторения загруженного временного файла:

$body = $HTTP_RAW_POST_DATA;
echo "\n REQUEST" . $body;

Но я получил только это:

file count=1 array(1) { ["user file"]=> array(5) { ["name"]=> string(12) "DrinkCO2.png" ["type"]=> string(9) "image/png" ["tmp_name"]=> string(14) "/tmp/phpxg7oLZ" ["error"]=> int(0) ["size"]=> int(190550) } } file is setTemp file uploaded. REQUEST 190550 image/png

person marciokoko    schedule 04.08.2014    source источник
comment
Вы смотрели на отправляемый/получаемый трафик с помощью чего-то вроде Wireshark или Charles Proxy?   -  person chedabob    schedule 05.08.2014
comment
Мне кажется, что ваш запрос от устройства iOS каким-то образом искажен (например, неправильная граница), не могли бы вы опубликовать Http Request + Body, созданный вашей формой браузера?   -  person dominik    schedule 07.08.2014
comment
Я добавил строки php и результат из сообщения в свой исходный вопрос внизу для ясности.   -  person marciokoko    schedule 08.08.2014
comment
Является ли это результатом запроса iOS или веб-формы?   -  person dominik    schedule 08.08.2014
comment
Результат отправки веб-формы тому же php-скрипту.   -  person marciokoko    schedule 09.08.2014
comment
Не могли бы вы опубликовать необработанное тело из запроса iOS?   -  person dominik    schedule 09.08.2014
comment
Есть новости по этому поводу? У меня та же проблема..   -  person Alvaro Talavera    schedule 03.09.2014
comment
У меня была проблема с двоеточием здесь-› name=\userfile\ : filename=\%@\\r\n   -  person marciokoko    schedule 04.09.2014
comment
Спасибо большое за этот пост. Я весь день убивал себя из-за NSURLSessions и данных POST, пытаясь загрузить файл. Я думаю, что неправильно понял заголовки или тип контента или что-то в этом роде. Это отлично сработало для меня.   -  person turkeyhundt    schedule 19.10.2014


Ответы (2)


Не хватало двоеточия, не хватало точки с запятой.

"name=\"userfile\" : filename=\"%@\"\r\n""

Должно быть

"name=\"userfile\"; filename=\"%@\"\r\n""

По крайней мере, это единственный способ, которым ваш код работал для меня (кстати, спасибо!).

person mgiesa    schedule 10.09.2014

У меня была проблема с точкой с запятой здесь->

"name=\"userfile\" ; filename=\"%@\"\r\n"" 

Так что это было уродливое тело в основном.

person marciokoko    schedule 04.09.2014