为啥 NSURLSession uploadTaskWithRequest:fromData: 无法上传到 php 服务器?

Posted

技术标签:

【中文标题】为啥 NSURLSession uploadTaskWithRequest:fromData: 无法上传到 php 服务器?【英文标题】:Why does NSURLSession uploadTaskWithRequest:fromData: fail to upload to php server?为什么 NSURLSession uploadTaskWithRequest:fromData: 无法上传到 php 服务器? 【发布时间】:2014-08-04 20:32:13 【问题描述】:

php 代码工作正常。我已经从同一服务器上的 html 表单上传了文件。上传的文件从 40K 到 2.0M 不等,所以它不是大小。在运行 PHP 5.3 的服务器上激活文件上传

我发现了很多这样的帖子(还没有答案):https://***.com/questions/19710388/using-nsurlsession-to-upload-an-image。

这个使用uploadTaskWithRequest:fromFile:而不是fromData:NSURLSession make sure Upload worked

这是 NSURLSessionDataTask 而不是 uploadTaskWithRequest:No data receiving with NSURLSession

有些帖子似乎说 uploadTaskWithRequest:fromData: 根本不起作用: NSURLSession: uploading assets with background transfer asynchronous upload with NSURLSession will not work but synchronous NSURLConnection does 和 Upload image from ios to 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://***.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 权限。正如我所说,我已经能够通过 html 表单从同一个 php 脚本上传并写入该文件夹。

http 错误代码的总响应为 200,count=0 以及 php 转储的 array(0) 。

这是来自应用程序中服务器的响应图像:

我在回应上传的临时文件后添加了这些行:

$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

【问题讨论】:

您是否查看过使用 Wireshark 或 Charles Proxy 等工具发送/接收的流量? 在我看来,您来自 iOS 设备的请求格式不正确(例如边界错误),您能否发布浏览器表单生成的 Http 请求 + 正文? 为了清楚起见,我将帖子中的 php 行和结果添加到我原来的问题底部。 这是 iOS 请求的结果还是 Web 表单的结果? 网页表单提交到同一个php脚本的结果。 【参考方案1】:

不是少了一个冒号,是少了一个分号。

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

应该是

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

至少这是您的代码为我工作的唯一方式(顺便谢谢!)。

【讨论】:

【参考方案2】:

这里的分号有问题->

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

所以它基本上是一个畸形的身体。

【讨论】:

以上是关于为啥 NSURLSession uploadTaskWithRequest:fromData: 无法上传到 php 服务器?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 NSURLSession uploadTaskWithRequest:fromData: 无法上传到 php 服务器?

为啥我的 NSURLSessionDownloadTask 下载不会到达我的客户端?

NSURLSession 啥时候运行?

NSURLSession 委托跨类拆分 - NSURLSession、NSURLUploadTask、NSURLDownloadTask

iOS开发系列-NSURLSession

学习NSURLSession