iOS核心笔记——网络编程-文件上传
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS核心笔记——网络编程-文件上传相关的知识,希望对你有一定的参考价值。
1、文件上传:
?重要
:当用户想向服务器传送客户端本地文件时,此时,需要使用POST
请求方式、NSURLSessionUploadTask
文件上传任务将文件传递至服务器。
1-1、技术点:
?重要
:①设置请求头信息,告诉服务器本次网络请求是在向服务器传送文件;②拼接要上传的文件的数据,拼接过程中一定要严格按照文件上传格式进行,否则,文件上传将会失败。
1-2、文件上传格式:
1、设置请求头信息:
?重要
:设置请求头,告诉服务器这是一次文件上传操作。
2、设置文件参数:
?重要
:设置请求体,将文件转换为二进制数据之后拼接在请求体中;拼接过程中一定要严格按照格式进行拼接,否则,将上传失败;上图所示,所有空行、换行均以\r\n
表示,上图中参数结束标记与\r\n
之间的空格实际是不存在的,只是为了方便阅读。
3、设置非文件参数:
?重要
:非文件参数与文件参数在设置Content-Disposition
时存在区别,文件参数:name
使用file
,表示这是一个文件,且还需向服务器传递filename
(即:文件上传至服务器之后的名称);非文件参数:只需设置name
,并用参数所对应的Key
表示该参数,然后将参数的值以二进制数据形式拼接在参数值的位置。
2、文件上传功能实现:
?重要
:文件上传,需要传递的数据可能非常的大;所以,不能使用简单的GET
请求,需要使用POST
请求完成。而且,文件上传需要设置请求头的Content-Type
信息,所以,需要使用可变的请求对象(即:NSMutableURLRequest
),使用KVC
方法设置该属性,告诉服务器这是一次文件上传操作。
2-1、创建上传请求操作:
1.- (void)upload{
2. // 1. 创建URL
3. NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
4.
5. // 2. 创建可变请求对象
6. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
7.
8. // 3. 设置请求方法为POST
9. request.HTTPMethod = @"POST";
10.
11. // 4. 设置请求头信息, 告诉服务器这是一个文件上传请求
12. // 就这个地方from错误, 应当是form; 就这一个错误害我花了1个多小时
13.// [request setValue:[NSString stringWithFormat:@"multipart/from-data; boundary=%@", kBoundary] forHTTPHeaderField:@"Content-Type"];
14. [request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", kBoundary] forHTTPHeaderField:@"Content-Type"];
15.
16. // 4. 获取默认配置信息
17. NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
18.
19. // 5. 创建会话对象
20. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
21.
22. // 6. 使用会话对象创建上传任务对象
23. [[session uploadTaskWithRequest:request fromData:[self bodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
24.
25. NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
26. }] resume];
27.}
?重要
:1、文件上传通常使用的是NSURLSessionTask
家族的NSURLSessionUploadTask
成员,设置完请求方法和请求头信息之后;使用会话对象创建文件上传会话任务,并调用resume
方法开启文件上传任务操作。
?重要
:2、在使用NSURLSessionUploadTask
进行文件上传时,也可以设置会话对象的代理;以便监听文件上传操作的进度,代理需要遵守【NSURLSessionDataDelegate
协议】。常见代理方法:1.
2.#pragma mark NSURLSessionDataDelegate
3.
4.//bytesSent 本次上传的文件数据大小
5.//totalBytesSent 已经上传的文件数据的总大小
6.//totalBytesExpectedToSend 文件的总大小
7.-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
8.{
9. NSLog(@"%f",1.0 * totalBytesSent / totalBytesExpectedToSend);
10.}
2-2、拼接文件参数和非文件参数:
1./**
2. * 拼接请求体数据, 经测试没有错误
3. */
4.- (NSMutableData *)getData{
5. // MARK: - 文件参数
6. // 1. 创建data
7. NSMutableData *fileData = [NSMutableData data];
8.
9. // 2. 拼接--分割线
10. NSString *str = [NSString stringWithFormat:@"--%@", kBoundary];
11. [fileData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
12.
13. [fileData appendData:newLine];
14.
15. // 4. 拼接Content-Disposition
16. str = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"Snip20161128_2.png\""];
17. [fileData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
18.
19. [fileData appendData:newLine];
20.
21. // 5. 拼接Content-Type, 文件的MIMEType格式: 大类型/小类型
22. str = [NSString stringWithFormat:@"Content-Type: image/png"];
23. [fileData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
24.
25. [fileData appendData:newLine];
26.
27. // 6. 拼接空行, 为确保在任何环境下都能够正确换行, 所以使用: \r\n
28.
29. [fileData appendData:newLine];
30.
31. // 7. 拼接文件数据
32. [fileData appendData:[NSData dataWithContentsOfFile:@"/Users/hehuafeng/Desktop/Snip20161128_2.png"]];
33.
34. // 8. 文件数据末尾换行
35. [fileData appendData:newLine];
36.
37. // MARK: - 非文件参数
38. // 1. 拼接分割线
39. str = [NSString stringWithFormat:@"--%@", kBoundary];
40. [fileData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
41.
42. [fileData appendData:newLine];
43.
44. // 2. 拼接Content-Disposition
45. str = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"username\""];
46. [fileData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
47.
48. [fileData appendData:newLine];
49. [fileData appendData:newLine];
50.
51. // 4. 拼接参数值
52. str = [NSString stringWithFormat:@"hahaha"];
53. [fileData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
54.
55. [fileData appendData:newLine];
56.
57. // MARK: - 拼接参数结束标记
58. str = [NSString stringWithFormat:@"--%@--", kBoundary];
59. [fileData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
60.
61. // MARK: - 返回拼接完毕的数据
62. return fileData;
63.}
?重要
:1、拼接文件非文件参数时,一定要严格按照格式进行拼接;否则,将无法上传文件。
?重要
:2、文件参数与非文件参数拼接步骤:--分割线
->换行(\r\n)
->文件参数的:Content-Dispositio
->换行(\r\n)
->文件参数的:Content-Type
->换行(\r\n)
->空一行(\r\n)
->二进制形式文件参数值
->换行(\r\n)
->--分割线
->换行(\r\n)
->非文件的:Content-Disposition
->换行(\r\n)
->空一行(\r\n)
->二进制形式非文件参数值
->换行(\r\n)
->--分割线--(即:结束标记)
2-3、文件上传使用的宏:
1.// 分割线, 为确保分析按正常换行; 所以, 使用\r\n
2.#define kBoundary @"----WebKitFormBoundarybH2OxPYq4hkfGHY6"
3.#define newLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]
以上是关于iOS核心笔记——网络编程-文件上传的主要内容,如果未能解决你的问题,请参考以下文章
iOS核心笔记——网络编程-NSURLSessionDownloadTask
(2020上半年第41天(代码审计-文件上传))小迪网络安全笔记