IOS上传图片、视频、文件原理

其实不应当归类到iOS当中,因为实际上是属于RFC 1867RFC 1341一类的东西。他们规定:这种需要执行 多部分POST(multipart POST)标准的情形,需要把图片啊视频啊等数据设置到HTTP【正文】当中,也就是要把表单项数据(也就是参数及其值)跟二进制文件数据相结合。


其中最让人望而生畏也最容易搞不懂的怕就是“边界字符串”了,其实就是任意内容的字符串(但是要两个横线开头),只要字符串的内容不与正文的其他部分发生冲突就行啦,比如:

NSString *boundaryStr=[[NSStringalloc]initWithFormat:@"--WriteByShareHoney"];

参见:http://www.ietf.org/rfc/rfc1341.txt

The  encapsulation  boundary   is defined   as  a  line  consisting  entirely  of  two  hyphen characters ("-", decimal code 45) followed by  the  boundary parameter value from the Content-Type header field.



【正文】需要由“边界字符串”封装,所以第一行就应该出现boundaryStr,而且之前【必须】要有换行。

这也要在【HTTPHeader】中对应的设置,如下:

//设置HTTPHeader
NSString *content=[[NSString alloc]initWithFormat:@"multipart/form-data;boundary=%@",boundaryStr];
[request setValue:content forHTTPHeaderField:@"Content-Type"];

即:Content-type: multipart/form-data, boundary=AaB03x 

这直接指定了http post请求的编码方式为multipart/form-data;

boundary=AaB03x则指AaB03x为“边界字符串”。
参考自http://borissun.iteye.com/blog/1338991



往下就好说了,把不同的字段用“边界字符串”分开:


//“边界字符串 单独占一行
--AaB03x    
//字段 field1。 content-disposition 个人理解为 内容特性 的意思。
content-disposition: form-data; name="field1"    
//换行2次 空行,必须的
//字段的值   单独占一行
Hello Boris!    
//“边界字符串 单独占一行
--AaB03x    
//字段 name 和 filename
content-disposition: form-data; name="pic"; filename="boris.png"    
//内容类型 与filename字段相对应
Content-Type: image/png    
//换行2次 空行,必须的
    
 <89504e47 ... 图片的二进制内容...>
 //“边界字符串 单独占一行
 --AaB03x 
 
 

这样看可能还有些蒙,其实就是合并几个字段:

Content-type: multipart/form-data, boundary=...    
content-disposition: form-data; name=...; filename=...    
Content-Type: ...   


参见代码吧:

//分界线的标识符,也就是“边界字符串”
NSString *TWITTERFON_FORM_BOUNDARY = @"AaB03x";


NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:_urlStr]
                                                       cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                   timeoutInterval:10];
//分界线添加"--"【前缀】,【重要】
NSString *MPboundary=[[NSString alloc]initWithFormat:@"--%@",TWITTERFON_FORM_BOUNDARY];


//结束符就是分界线
NSString *endMPboundary=[[NSString alloc]initWithFormat:@"%@--",MPboundary];




NSData *data = nil;
if (UIImagePNGRepresentation(image)) {
     data = UIImagePNGRepresentation(image);
}
else
{
    data = UIImageJPEGRepresentation(image, 1.0);
}


//http body的字符串
NSMutableString *body=[[NSMutableString alloc]init];


//遍历参数集合,将键值对合并到body(正文)中去
NSArray *keys= [postParems allKeys];
for(int i=0;i<[keys count];i++)
{

    NSString *key=[keys objectAtIndex:i];
    //如果key不是pic,说明value是字符类型,比如name:Boris
    if(![key isEqualToString:@"pic"])
    {
        //添加分界线,【换行】
        [body appendFormat:@"%@\r\n",MPboundary];
        //添加字段名称,【换2行】
        [body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key];
        //添加字段的值
        [body appendFormat:@"%@\r\n",[postParems objectForKey:key]];
    }
}


添加分界线,换行
[body appendFormat:@"%@\r\n",MPboundary];


//声明pic字段,文件名为boris.png
[body appendFormat:@"Content-Disposition: form-data; name=\"uploadedfile\"; filename=\"boris.png\"\r\n"];


//声明上传文件的格式
if (UIImagePNGRepresentation(image))
{
//【换2行】
    [body appendFormat:@"Content-Type: image/png\r\n\r\n"];
}
else
{
    [body appendFormat:@"Content-Type: image/jpg\r\n\r\n"];
}


//声明结束符,主意有【换行】
NSString *end=[[NSString alloc]initWithFormat:@"\r\n%@",endMPboundary];


//声明myRequestData,用来放入http body
NSMutableData *myRequestData=[NSMutableData data];
//将body字符串转化为【UTF8格式的二进制】
[myRequestData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
//将image的data加入
[myRequestData appendData:data];
//加入结束符--AaB03x--  【正文】封装完毕。
[myRequestData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];


//设置【HTTPHeader】中Content-Type的值
NSString *content=[[NSString alloc]initWithFormat:@"multipart/form-data; boundary=%@",TWITTERFON_FORM_BOUNDARY];
//设置HTTPHeader
[request setValue:content forHTTPHeaderField:@"Content-Type"];
//设置Content-Length
[request setValue:[NSString stringWithFormat:@"%d", [myRequestData length]] forHTTPHeaderField:@"Content-Length"];
//设置【http body】
[request setHTTPBody:myRequestData];
//设置【http method】
[request setHTTPMethod:@"POST"];


[NSURLConnection connectionWithRequest:request delegate:self];



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


另:

如果上传的文件很大,数10m甚至上100m,建议使用NSInputStream从文件中读取,而不是用NSData从内存中获取数据,不然怕是内存吃紧,从而app也就不稳定了。



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值