標籤:
以上是抓包HTML input file標籤上傳的內容
只要類比上面http 的header跟body就可以成功。
整體說明:
post 上傳檔案時,以在http body裡面帶參數,參數的格式,根據RFC1867協議要求寫成如下
在http header 裡面定義 boundary ,boundary的值為body裡面分隔參數的標誌。
Content-Type: multipart/form-data; boundary=----------LlcUploadTaskWithRequest
假設 post 過去,兩個參數 user="loganv"&pwd="123456" 跟一個二進位檔案 file,服務端通過欄位 ‘file‘ 擷取檔案流,檔案名稱字叫做filename.png。
------------LlcUploadTaskWithRequestContent-Disposition: form-data; name="user"
loganv------------LlcUploadTaskWithRequestContent-Disposition: form-data; name="pwd"
123456------------LlcUploadTaskWithRequestContent-Disposition: form-data; name="file"; filename="filename.png"Content-Type: application/octet-streamÿØÿàJFIFHHÿá¼ExifMM*JR(?i(此處為上傳的二進位檔案資料)
把下面這個體當成一對整體來看
------------LlcUploadTaskWithRequestContent-Disposition: form-data; name="user"loganv
第一行:以header 裡面定義的 boundary的值,在前面加"--",,以"\r\n"結尾
第二行:定義了參數的鍵 user ,以"\r\n"結尾
第三行:"\r\n"
第四行:參數的值 123456,以"\r\n"結尾
如果參數是檔案,需要在上面的低二行下面增加一行定義檔案的類型 MIME type
iOS 實現上傳,swift2.0 主要代碼
第一步:自訂boundary分割標誌,在給header加個 Content-Type;
let post_boundary = "----------LlcUploadTaskWithRequest"
let reqq = NSMutableURLRequest(URL: NSURL(string: "http://172.16.0.199/upload/uploadIpa.php")!)
reqq.HTTPMethod = "POST"
reqq.setValue(post_boundary, forHTTPHeaderField: "Content-Type")
第二步:拼接http body 需要 post 過去的參數,跟二進位檔案;服務端通過欄位 ‘file‘ 擷取檔案流;
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
var paramStr = ""
if param != nil{
for (k, v) in param!{
paramStr += uploadPostParamInBody(k, nameValue: v.description)
}
}
paramStr += uploadPostParamInBody("file", filename: "filename.png")
let boundary = paramStr.dataUsingEncoding(NSUTF8StringEncoding)?.mutableCopy() as? NSMutableData
let pdata = NSData(data: multipartFormData!)
let boundary_end = ("\r\n--" + post_boundary + "--").dataUsingEncoding(NSUTF8StringEncoding)
boundary?.appendData(pdata)
boundary?.appendData(boundary_end!)
拼接參數的方法
//---- uploadTaskWithRequest 上傳 /* name: post body裡面帶的參數的名稱,伺服器根據這個名稱取得對應的參數值; filename: 檔案的名字比如 logo.png; MIMEtyp: 為application/octet-stream代表任何二進位流都可以,圖片傳image/jpeg; */ public func uploadPostParamInBody(name: String, filename: String = "", nameValue: String = "", MIMEtype: String = "application/octet-stream") -> String{ var content = "--" + LlcHttpRequest.post_boundary + "\r\n" if filename == ""{ content += "Content-Disposition: form-data; name=\"\(name)\"\r\n\r\n"; content += "\(nameValue)\r\n"; } else{ content += "Content-Disposition: form-data; name=\"\(name)\"; filename=\"\(filename)\"\r\n"; content += "Content-Type: \(MIMEtype)\r\n\r\n"; } return content }
第三步:請求
let task = session.uploadTaskWithRequest(req.request, fromData: boundary){ (obj: NSData?, resp: NSURLResponse?, err: NSError?) -> Void in if let respHtml = resp as? NSHTTPURLResponse { if respHtml.statusCode == 200 { if obj != nil{ var resu: AnyObject? = String(data: obj!, encoding: NSUTF8StringEncoding) if let json = try? NSJSONSerialization.JSONObjectWithData(obj!, options: .AllowFragments){ resu = json } } } } else{ fail(resp: resp, error: err) } if err != nil{ fail(resp: resp, error: err) } } task.resume()
完了!
附上PHP服務端簡單接受檔案上傳的代碼
<?php $text = isset($_REQUEST[‘text‘]) ? $_REQUEST[‘text‘] : ""; echo ‘success<br>‘; if ($_FILES["file"]["error"] > 0){ echo "Error: " . $_FILES["file"]["error"] . "<br />"; } elseif ($_FILES["file"]["size"] > 20*1024*1024) { echo ‘file too big‘; } else{ echo "Upload: " . $_FILES["file"]["name"] . "<br />"; echo "Type: " . $_FILES["file"]["type"] . "<br />"; echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />"; echo "Stored in: " . $_FILES["file"]["tmp_name"] . ‘<br />‘; $isipa = false; $uploadSrc = ‘../download/ipa/‘.$_FILES["file"]["name"]; if ( preg_match(‘/\.ipa$/‘, $_FILES["file"]["name"]) ) { $isipa = true; $uploadSrc = ‘../download/ipa/‘.‘test01.ipa‘; } if (file_exists($uploadSrc) && $isipa ){ // echo $_FILES["file"]["name"] . " already exists. "; rename($uploadSrc, ‘../download/ipa/‘.date(‘Y-m-d H:i:s‘).‘.ipa‘); } move_uploaded_file($_FILES["file"]["tmp_name"], $uploadSrc); echo "Stored in: " . $uploadSrc.‘<br>‘; echo ‘上傳成功!‘; }
iOS上傳檔案,有關http上傳協議-RFC1867