iOS 原生小文件上傳

參考文章:http://www.cocoachina.com/bbs/read.php?tid=89985

協(xié)議

iOS 中上傳文件需要自己實(shí)現(xiàn)http協(xié)議
在http協(xié)議中上傳文件是有固定格式的,格式如下

Content-type: multipart/form-data, boundary=abcde
 
--abcde
content-disposition: form-data; name="field1"
 
Hello Boris!
--abcde
content-disposition: form-data; name="pic"; filename="boris.png"
Content-Type: image/png
 
... contents of boris.png ...
--abcde--

上面的每一個(gè)換行和空格都是必須的

Content-type: multipart/form-data,boundary=abcde 

固定用法,在http協(xié)議中規(guī)定向服務(wù)器發(fā)送數(shù)據(jù)時(shí)需要使用multipart/form-data
規(guī)定了http中分隔線的標(biāo)識(shí),在http中只要見到--abcde這個(gè)字符串,就被理解為這是一個(gè)分隔符,abcde是一個(gè)隨機(jī)字符串,具體長(zhǎng)度限制我沒有驗(yàn)證過,前面加--也是協(xié)議規(guī)定

--abcde

分隔線

content-disposition: form-data; name="field1"

Hello Boris!

這里聲明了請(qǐng)求中的一個(gè)字段key = field1,value = Hello Boris!,這里兩行之間的空行是必須的,是http協(xié)議的規(guī)定

--abcde

不同的字段需要用分隔線分開

content-disposition: form-data; name="pic"; filename="boris.png"
Content-Type: image/png
 
... contents of boris.png ...

這里聲明文件字段,這里以圖片為例
name是與后臺(tái)規(guī)定的文件標(biāo)識(shí)
filename是后臺(tái)存儲(chǔ)文件時(shí)的文件名
Content-Type是文件類型,這里是圖片類型
... contents of boris.png ...是文件的二進(jìn)制內(nèi)容

iOS 實(shí)現(xiàn)

- (void)uploadFileWithURL:(NSString *)url
                      name:(NSString *)name
                  filename:(NSString *)filename
               contentType:(NSString *)contentType
                      file:(NSData *)data
                    params:(NSDictionary *)params
                   success:(TCUploadFileMangerSuccess)success
                      fail:(TCUploadFileMangerFail)fail
{
    self.success = success;
    self.fail = fail;
    //分界線標(biāo)識(shí)符,這里構(gòu)造了一個(gè)隨機(jī)字符串
    NSString *RANDOM_STRING = [NSString tc_getRandomStringWithType:TCRandomStringTypeLowercase | TCRandomStringTypeCapital | TCRandomStringTypeNumber
                                                            length:16];
    //根據(jù)url初始化request
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
                                                           cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                       timeoutInterval:10.0];
    //分界線 --randomString
    NSString *boundary = [[NSString alloc] initWithFormat:@"--%@",RANDOM_STRING];
    //獲取圖片data
//    UIImage *image = (UIImage *)file;
//    NSData *data = UIImagePNGRepresentation(image);
    //構(gòu)造http body字符串
    NSMutableString *body = [[NSMutableString alloc] init];
    NSArray *keys = [params allKeys];
    for (id objc in keys) {
        //添加分隔線 然后換行
        [body appendFormat:@"%@\r\n",boundary];
        //添加字段名稱 然后換兩行
        [body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",objc];
        //添加字段的值 然后換行
        [body appendFormat:@"%@\r\n",params[objc]];
    }
    //添加分界線 然后換行
    [body appendFormat:@"%@\r\n",boundary];
    //聲明圖片字段
    [body appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",name,filename];
    //聲明上傳文件的格式
    [body appendFormat:@"Content-Type: %@\r\n\r\n",contentType];
    //聲明結(jié)束符 --randomString--
    NSString *endBoundary = [[NSString alloc] initWithFormat:@"\r\n%@--",boundary];
    //聲明myRequestData,用來放入http body
    NSMutableData *myRequestData = [NSMutableData data];
    //將body字符串轉(zhuǎn)換為UTF8編碼
    [myRequestData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
    //將image的data放入myRequestData
    [myRequestData appendData:data];
    //加入結(jié)束符
    [myRequestData appendData:[endBoundary dataUsingEncoding:NSUTF8StringEncoding]];
    //設(shè)置http header中Content-Type的值
    NSString *content = [[NSString alloc] initWithFormat:@"multipart/form-data; boundary=%@",RANDOM_STRING];
    //設(shè)置http header
    [request setValue:content forHTTPHeaderField:@"Content-Type"];
    //設(shè)置Content-Length
    [request setValue:[NSString stringWithFormat:@"%lu",(unsigned long)[myRequestData length]] forHTTPHeaderField:@"Content-Length"];
    //設(shè)置http body
    [request setHTTPBody:myRequestData];
    //設(shè)置http method
    [request setHTTPMethod:@"POST"];
    //建立連接
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

備注

這個(gè)方法中沒有處理大文件上傳,一次性讀取大文件的話內(nèi)存會(huì)瞬間爆炸,解決這個(gè)問題可以在此基礎(chǔ)上再做分片

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容