2014-01-16 86 views
4

編輯:好的,我只是設置內容類型的標題爲multipart/form-data沒有區別。我的原始問題如下:NSURLSessionUploadTask不傳遞文件到php腳本


這是我的第一個關於堆棧溢出的問題,我希望我做得對。

我只學習Objective-C,最近完成了斯坦福大學的在線版課程。我對php和html幾乎一無所知。我使用的php腳本和html大多是從教程中複製的。 Obj-C使更多對我意義重大。

問題:

我有一個PHP腳本。它上傳一個圖像文件。當從服務器上同一文件夾中的html文件調用時,它可以正常工作。我試圖從我的obj-c調用相同的腳本來工作。它似乎運行,它返回200,obj-c調用php,但沒有文件出現在聯機文件夾中。

因爲它只在ios7中引入,所以在網上似乎很少有關於此。我沒有找到處理文件上傳的例子,它們都處理下載,只是說上傳類似。我所做的似乎滿足了我找到的任何教程。

我所知道的是:

  • PHP的作品,並上載文件,當它被稱爲形式在服務器上的HTML文件
  • 的OBJ-C是絕對調用PHP腳本(我寫了一些日誌記錄(使用file_put_contents)到php確認腳本被稱爲當我運行obj-c)
  • obj-c是非常肯定上傳圖像文件(如果我使用委託方法在obj -c中顯示上傳進度)
  • 但php腳本沒有收到該文件(我寫入php的日誌記錄顯示$ _FILES在從obj-c調用時沒有值。當從HTML調用它按預期工作)
  • 我剛剛編輯的PHP來記錄它收到的標題,它確實得到圖像文件的內容長度。

事情可能重要

  • 我不加入任何HTML頭,沒有我所看到的教程說,我要(與NSURLSessionUploadTask)我假設NSURLSessionUploadTask爲你排序呢?或者這是我的問題?
  • [response description]返回200,引用:{URL :(PHP腳本URL)} {狀態碼:200,標題{0}連接=「保持活動」; 「Content-Type」=「text/html」; 日期=「2014年1月16日星期四19:58:10 GMT」; 「Keep-Alive」=「timeout = 5,max = 100」; Server = Apache; 「Transfer-Encoding」=身份; }}
  • html指定了enctype =「multipart/form-data」,或許這必須在我的obj-c某處工作?
  • 我只在目前的模擬器上運行它
  • 任何幫助將非常感激!謝謝:)
  • 編輯,我剛剛編輯了下面的代碼來顯示[request setHTTPMethod:@「POST」],而不是[request setHTTPMethod:@「PUSH」],但它沒有改變。

這裏是目標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> 

+0

你檢出了http://www.php.net/move_uploaded_file嗎?接收文件是非常直接與PHP,結合$ _FILES超級全局和move_uploaded_file(而不是你正在做的文件流)。還有,你在哪裏指定你的目標c中的輸入名稱是「文件」? –

+1

感謝您的回覆:) 是的,我看了看。我也試過這個,結果相同(對不起,我不知道如何在回覆中格式化代碼): $ file = $ _FILES [「file」] [「tmp_name」]; $ newfile =「upload /」。 $ _FILES [ 「文件」] [ 「名稱」]; if(!copy($ file,$ newfile)){ echo「未能複製$ file ... \ n」; } 我不確定你的第二個問題是什麼意思? – narco

+0

@Martin Sommervold我剛剛在看你的評論,因爲我一直在試圖找出這個問題的一週最好的一部分(並沒有其他人回覆)。我可能誤解了你的評論。你是說我的PHP錯了嗎?我的obj-c沒有上傳到$ _FILES嗎?在此先感謝 – narco

回答

0

我剛纔已經回答同樣的問題在這裏: 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設備上的保存,上傳和保存到服務器的代碼。

我希望幫助。

+0

自己用uploadTaskWithRequest遇到了麻煩:fromFile:completion:你的示例代碼實際上會拋出一個異常。如果使用後臺NSURLSession,則不支持完成塊。 我一直在努力讓uploadTaskWithRequest在前臺嚴格執行功能 - 並且標題出去了,但不是文件。開始懷疑完成塊的方法剛剛破解 – Todd