底层服务器如何传输文件,iOS文件传输的底层实现

一.前言

之前对AFNetWorking二次封装上传图片的方法是以文件流的方式上传的,上传文件有两张方式:1.已文件流的方式上传 2.将image转成NSData,在进行base64加密上传(NSString imageString = [data base64EncodedStringWithOptions:0];转成base64字符串imageString,再传给给后台,在传参中需要添加图片的类型(@“png”或@“jpg”等))。两种方式选择哪一种,取决于后台以哪种方式接受文件。对于第二种方式很简单,第一种方式AFNetWoring也封装好了,下面我们从最底层文件传输探讨,也就是AFNetWoring内部是怎么实现文件流传输的。即探讨一下

-(void)appendPartWithFileData:(NSData *)data

name:(NSString *)name

fileName:(NSString *)fileName

mimeType:(NSString *)mimeType;

到底是怎么实现的

二.单个文件传输(AFN在个别情况下不能完成,可直接用最底层方法传输)

/ /分割符:必须不能包含中文

#define CZBoundary @"baidu"

/**

* 上传文件

*

* @param fileData fileData 上传文件的二进制数据

* @param fieldName fieldName 上传到服务器的字段名

* @param fileNamefileName上传文件名

*/

- (void)uploadFile:(NSData *)fileData fieldName:(NSString

*)fieldName fileName:(NSString *)fileName

{

//url upload.php 是验证上传的脚本 它内部规定了保存在服务器哪个路径 和传入服务器的字段名 这是后台给的路径

NSURL *url = [NSURL URLWithString:@"http://192.168.51.9/post/upload.php"];

//request

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

//设置请求方法

request.HTTPMethod = @"POST";

/* Content-Type

multipart/form-data; boundary=itcast*/

//设置contentType

[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",CZBoundary] forHTTPHeaderField:@"Content-Type"];

//设置请求体

request.HTTPBody = [self fileData:fileData fieldName:fieldName fileName:fileName];

//发送请求

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {

NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

NSLog(@"%@---%@",response,dict);

}];

}

/**

* 设置请求体二进制

*

* @param fileData fileData 上传文件的二进制数据

* @param fieldName fieldName description

* @param fileNamefileName上传文件名

*

* @return 请求体

*/

- (NSData *)fileData:(NSData *)fileData fieldName:(NSString

*)fieldName fileName:(NSString *)fileName

{

//创建一个可变二进制数据

NSMutableData *dataM = [NSMutableData data];

//创建一个可变字符串

NSMutableString *strM = [NSMutableString string];

[strM appendFormat:@"--%@\r\n",CZBoundary];

[strM appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",fieldName,fileName];

[strM appendFormat:@"Content-Type: application/octet-stream\r\n\r\n"];

//将strM的内容拼接到dataM中

[dataM appendData:[strM dataUsingEncoding:NSUTF8StringEncoding]];

//拼接文件的二进制数据

[dataM appendData:fileData];

//拼接结尾标识

NSString *tail = [NSString stringWithFormat:@"\r\n--%@--",CZBoundary];

[dataM appendData:[tail dataUsingEncoding:NSUTF8StringEncoding]];

//拼接文件的二进制数据

return dataM;

}

调用示范

-(void)touchesBegan:(NSSet *)touches withEvent:

(UIEvent *)event

{

NSString *filePath = [[NSBundle

mainBundle]pathForResource:@"1.png" ofType:nil];

NSData *fileData = [NSData dataWithContentsOfFile:filePath];

[self uploadFile:fileData fieldName:@"userfile"

fileName:@"1.png"];

}

三.多个文件传输

/**

* 上传多个文件

*

* @param fileDict 多个文件字典

* @param fieldName 上传到服务器的字段

* @param params 普通参数字典

*/

- (void)uploadFile:(NSDictionary *)fileDict fieldName:

(NSString *)fieldName params:(NSDictionary *)params

{

//url upload.php 是验证上传的脚本 它内部规定了保存在服务器哪个路径 这是后台给的路径

NSURL *url = [NSURL URLWithString:@"http://localhost/post/upload-m.php"];

//request

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

//设置请求方法

request.HTTPMethod = @"POST";

/* Content-Type

multipart/form-data; boundary=itcast*/

//设置contentType

[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",CZBoundary] forHTTPHeaderField:@"Content-Type"];

//设置请求体

request.HTTPBody = [self fileData:fileDict fieldName:fieldName params:params];

//发送请求

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {

NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

NSLog(@"%@---%@",response,dict);

}];

}

/**

* 设置请求体二进制

*

@param fileDict 多个文件字典

* @param fieldName 上传到服务器的字段

* @param params 普通参数字典

*

* @return 请求体

*/

- (NSData *)fileData:(NSDictionary *)fileDict fieldName:

(NSString *)fieldName params:(NSDictionary *)params

{

//创建一个可变二进制数据

NSMutableData *dataM = [NSMutableData data];

//遍历文件字典

[fileDict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull fileName, id fileData, BOOL * _Nonnull stop) {

//创建一个可变字符串

NSMutableString *strM = [NSMutableString string];

[strM appendFormat:@"--%@\r\n",CZBoundary];

[strM appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",fieldName,fileName];

[strM appendFormat:@"Content-Type: application/octet-stream\r\n\r\n"];

//将strM的内容拼接到dataM中

[dataM appendData:[strM dataUsingEncoding:NSUTF8StringEncoding]];

//拼接文件的二进制数据

[dataM appendData:fileData];

//拼接当前文件结尾标志

NSString *tail = [NSString stringWithFormat:@"\r\n--%@\r\n",CZBoundary];

[dataM appendData:[tail dataUsingEncoding:NSUTF8StringEncoding]];

}];

//遍历普通参数 key是接受普通参数的字段 obj是普通参数内容

[params enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {

//创建一个可变字符串

NSMutableString *strM = [NSMutableString string];

[strM appendFormat:@"Content-Disposition: form-data; name=%@\r\n\r\n",key];

[strM appendFormat:@"%@",obj];

[dataM appendData:[strM dataUsingEncoding:NSUTF8StringEncoding]];

}];

//拼接结尾标识

NSString *tail = [NSString stringWithFormat:@"\r\n--%@--",CZBoundary];

[dataM appendData:[tail dataUsingEncoding:NSUTF8StringEncoding]];

//

// //拼接文件的二进制数据

return dataM;

}

多个文件上传调用示范

/ /分割符:必须不能包含中文

#define CZBoundary @"baidu"

-(void)touchesBegan:(NSSet *)touches withEvent:

(UIEvent *)event

{

NSString *filePath1 = [[NSBundle

mainBundle]pathForResource:@"1.png" ofType:nil];

NSData *fileData1 = [NSData

dataWithContentsOfFile:filePath1];

NSString *filePath2 = [[NSBundle

mainBundle]pathForResource:@"11.png" ofType:nil];

NSData *fileData2 = [NSData dataWithContentsOfFile:filePath2];

/ /普通参数

NSString *username = @"file";

//接受文件数据的字段名:userfile[] 接受普通参数的字段

名:username

//文件字典

NSDictionary *fileDict =

@{@"1.png":fileData1,@"11.png":fileData2};

//普通参数字典 @"username"后台给的传入普通参数的字段名

value自己传入的参数

NSDictionary *params = @{@"username":username};

//确定要传入的文件 找后台要路径和传入服务器的字段名 确定参数

[self uploadFile:fileDict fieldName:@"userfile[]" params:params];

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值