1. 程式人生 > >iOS使用表單流上傳檔案(圖片/文字/...)

iOS使用表單流上傳檔案(圖片/文字/...)

#define HTTP_CONTENT_BOUNDARY @"----WebKitFormBoundarywpMAGHPPMfSNBkkK----"

+ (BOOL)httpPutDataWithUploadDate:(NSString *)uploadDate UserName:(NSString *)userName FilePath:(NSString *)filePath{

    NSString *strUrl = [clsOtherFun getUploadCrashFileURL];
    strUrl = [strUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    NSURL
*url = [NSURL URLWithString:strUrl]; NSData *data = [NSData dataWithContentsOfFile:filePath]; NSString *fileName = [filePath lastPathComponent]; NSMutableString *bodyStr = [[NSMutableString alloc] init]; [bodyStr appendString:[NSString stringWithFormat:@"--%@\nContent-Disposition: form-data; name=\"UploadDate\";\n\n%@\n"
, HTTP_CONTENT_BOUNDARY, uploadDate]]; [bodyStr appendString:[NSString stringWithFormat:@"--%@\nContent-Disposition: form-data; name=\"UserName\";\n\n%@\n", HTTP_CONTENT_BOUNDARY, userName]]; [bodyStr appendString:[NSString stringWithFormat:@"--%@\nContent-Disposition: form-data; name=\"System\";\n\niOS\n"
, HTTP_CONTENT_BOUNDARY]]; [bodyStr appendString:[NSString stringWithFormat:@"--%@\nContent-Disposition: form-data; name=\"%@\"; filename=\"%@\"\nContent-Type: %@\n\n",HTTP_CONTENT_BOUNDARY, @"file1", fileName, @"text/plain"]]; NSMutableData *httpBody = [NSMutableData data]; [httpBody appendData:[bodyStr dataUsingEncoding:NSUTF8StringEncoding]]; [httpBody appendData:data]; [httpBody appendData:[[NSString stringWithFormat:@"\n--%@",HTTP_CONTENT_BOUNDARY] dataUsingEncoding:NSUTF8StringEncoding]]; NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] init]; [urlRequest setURL:url]; [urlRequest setHTTPMethod:@"POST"]; [urlRequest setTimeoutInterval: 60000]; [urlRequest setValue:[NSString stringWithFormat:@"%@", @(httpBody.length)] forHTTPHeaderField:@"Content-Length"]; [urlRequest setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",HTTP_CONTENT_BOUNDARY] forHTTPHeaderField:@"Content-Type"]; urlRequest.HTTPBody = httpBody; NSHTTPURLResponse *httpResponse = nil; NSError *error = [[NSError alloc] init]; NSData *responseData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&httpResponse error:&error]; if (responseData != nil) { // NSMutableDictionary *dict = NULL; //IOS5自帶解析類NSJSONSerialization從response中解析出資料放到字典中 // NSString *responseStr = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&error]; //若狀態碼為200,則伺服器訪問成功! if (httpResponse == nil) { NSLog(@"url: %@\nerror_code: %@", strUrl, error); } if (httpResponse.statusCode != 200) { NSLog(@"url: %@\nHTTP response: %ld", strUrl, (long)httpResponse.statusCode); } //若後臺返回字串“1”,則檔案上傳成功! NSString *resultStr = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; if (httpResponse.statusCode == 200 && [resultStr isEqualToString:@"1"]) { return YES; } else{ return NO; } NSLog(@"upload_file_resultStr: %@", resultStr); } return NO; }

這是我用Safari擷取的POST請求的表單流格式,見下圖:
這裡寫圖片描述
(因後臺伺服器提供的介面已不可訪問,故顯示的內容不太契合。若訪問正常,則“No user permission.”顯示為下圖的內容。)

這裡寫圖片描述

上面就是需要拼接的表單流格式。注意:一定要嚴格遵循這種格式!
圖中每個框框的內容為對應引數的格式。

這時候只需要我們拼接的引數、字串格式是嚴格遵循以上格式。
這裡寫圖片描述

上面的程式碼不免顯得臃腫,也難以通用。

下面介紹一種更為簡單便捷的方式,當然同樣基於POST請求。沒錯,主角就是AFNetworking,AFHTTPSessionManager為我們提供了
*- (NSURLSessionDataTask )POST:(NSString *)URLString
parameters:(id)parameters
constructingBodyWithBlock:(void (^)(id formData))block
progress:(nullable void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
failure:(void (^)(NSURLSessionDataTask task, NSError *error))failure*
這一方法,自從用了它,我們的程式碼處理一切都變得簡單起來。

關鍵程式碼:

            AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
            session.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:
                                                                 @"application/json",
                                                                 @"text/json",
                                                                 @"text/javascript",
                                                                 @"text/html",
                                                                 @"text/plain",
                                                                 nil];
            [session POST:[Utils getVerificationURL]
            //我們的引數集合
               parameters:@{@"UserID":userIDStr,
                            @"IDNumber":idNumStr,
                            @"RealName":realNameStr,
                            @"File1":fileName1,
                            @"File2":fileName2}
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileData:photoData1 name:@"File1"
                            fileName:fileName1 mimeType:@"image/jpeg"];
    [formData appendPartWithFileData:photoData2 name:@"File2"
                            fileName:fileName2 mimeType:@"image/jpeg"];

}
                 progress:^(NSProgress * _Nonnull uploadProgress) {
                     NSLog(@"service progress...");
                 }
                  success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                      if (responseObject != nil) {

                          // {"Code":1,"Msg":"1.成功; 3.使用者不存在或無效; 4.使用者已經完成稽核;  5.寫入資料失敗 "}
                          // 若後臺返回"Code"欄位為“1”,則檔案上傳成功!
                          NSLog(@"POST Response Code:%@", [responseObject valueForKey:@"Code"]);
                          //responseObject的格式已經為JSON資料格式。
                          if ([[responseObject valueForKey:@"Code"] integerValue] == 1){
                              //do you what you want.
                              //[session invalidateSessionCancelingTasks:YES];
                          }
                      }
                  }
                  failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                      NSLog(@"POST Error: %@", error.description);
                  }
             ];
        }

文章難免會有紕漏之處,若有發現,還望各位同仁提出。讓我們共同交流,一起進步!