关于iOS如何实现视频和图片的上传, 我们先理清下思路,然后小编根据思路一步一步给大家详解实现过程。
思路:
#1. 如何获取图片?
#2. 如何获取视频?
#3. 如何把图片存到缓存路径中?
#4. 如何把视频存到缓存路径中?
#5. 如何上传?
接下来, 我们按照上面的思路一步一步实现
首先我们新建一个类, 用来储存每一个要上传的文件uploadModel.h
1
2
3
4
5
6
7
|
# import <Foundation/Foundation.h> @interface uploadModel : NSObject @property (nonatomic, strong) NSString *path; @property (nonatomic, strong) NSString *type; @property (nonatomic, strong) NSString *name; @property (nonatomic, assign) BOOL isUploaded; @end |
#1. 如何获取图片?
从相册选择 或者 拍照,
这部分可以用UIImagePickerController来实现
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
- ( void )actionPhoto { UIAlertController *alertController = \ [UIAlertController alertControllerWithTitle:@ "" message:@ "上传照片" preferredStyle:UIAlertControllerStyleActionSheet]; UIAlertAction *photoAction = \ [UIAlertAction actionWithTitle:@ "从相册选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { NSLog(@ "从相册选择" ); self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; self.imagePicker.mediaTypes = @[(NSString *)kUTTypeImage]; self.imagePicker.allowsEditing = YES; [self presentViewController:self.imagePicker animated:YES completion:nil]; }]; UIAlertAction *cameraAction = \ [UIAlertAction actionWithTitle:@ "拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { NSLog(@ "拍照" ); if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; self.imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto; self.imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceRear; self.imagePicker.allowsEditing = YES; [self presentViewController:self.imagePicker animated:YES completion:nil]; } }]; UIAlertAction *cancelAction = \ [UIAlertAction actionWithTitle:@ "取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { NSLog(@ "取消" ); }]; [alertController addAction:photoAction]; [alertController addAction:cameraAction]; [alertController addAction:cancelAction]; [self presentViewController:alertController animated:YES completion:nil]; } |
#2. 如果获取视频?
从相册选择 或者 拍摄
这部分也可以用UIImagePickerController来实现
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
- ( void )actionVideo { UIAlertController *alertController = \ [UIAlertController alertControllerWithTitle:@ "" message:@ "上传视频" preferredStyle:UIAlertControllerStyleActionSheet]; UIAlertAction *photoAction = \ [UIAlertAction actionWithTitle:@ "从视频库选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { NSLog(@ "从视频库选择" ); self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; self.imagePicker.mediaTypes = @[(NSString *)kUTTypeMovie]; self.imagePicker.allowsEditing = NO; [self presentViewController:self.imagePicker animated:YES completion:nil]; }]; UIAlertAction *cameraAction = \ [UIAlertAction actionWithTitle:@ "录像" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { NSLog(@ "录像" ); self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; self.imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceRear; self.imagePicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera]; self.imagePicker.videoQuality = UIImagePickerControllerQualityType640x480; self.imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo; self.imagePicker.allowsEditing = YES; [self presentViewController:self.imagePicker animated:YES completion:nil]; }]; UIAlertAction *cancelAction = \ [UIAlertAction actionWithTitle:@ "取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { NSLog(@ "取消" ); }]; [alertController addAction:photoAction]; [alertController addAction:cameraAction]; [alertController addAction:cancelAction]; [self presentViewController:alertController animated:YES completion:nil]; } |
#3, 关于缓存, 如何把照片存入缓存目录?
这部分我们先考虑缓存目录, 一般存在Document 或者 Temp里面
我们给图片和视频各创建一个缓存目录:
1
2
|
#define PHOTOCACHEPATH [NSTemporaryDirectory() stringByAppendingPathComponent:@ "photoCache" ] #define VIDEOCACHEPATH [NSTemporaryDirectory() stringByAppendingPathComponent:@ "videoCache" ] |
把UIImage存入缓存的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//将Image保存到缓存路径中 - ( void )saveImage:(UIImage *)image toCachePath:(NSString *)path { NSFileManager *fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:PHOTOCACHEPATH]) { NSLog(@ "路径不存在, 创建路径" ); [fileManager createDirectoryAtPath:PHOTOCACHEPATH withIntermediateDirectories:YES attributes:nil error:nil]; } else { NSLog(@ "路径存在" ); } //[UIImagePNGRepresentation(image) writeToFile:path atomically:YES]; [UIImageJPEGRepresentation(image, 1 ) writeToFile:path atomically:YES]; } |
4. 如何把视频存入缓存?
把视频存入缓存的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
//将视频保存到缓存路径中 - ( void )saveVideoFromPath:(NSString *)videoPath toCachePath:(NSString *)path { NSFileManager *fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:VIDEOCACHEPATH]) { NSLog(@ "路径不存在, 创建路径" ); [fileManager createDirectoryAtPath:VIDEOCACHEPATH withIntermediateDirectories:YES attributes:nil error:nil]; } else { NSLog(@ "路径存在" ); } NSError *error; [fileManager copyItemAtPath:videoPath toPath:path error:&error]; if (error) { NSLog(@ "文件保存到缓存失败" ); } } |
从缓存获取图片的方法:
1
2
3
4
5
6
7
8
|
//从缓存路径获取照片 - (UIImage *)getImageFromPath:(NSString *)path { NSFileManager *fileManager = [NSFileManager defaultManager]; if ([fileManager fileExistsAtPath:path]) { return [UIImage imageWithContentsOfFile:path]; } return nil; } |
上传图片和视频的时候我们一般会利用当前时间给文件命名, 方法如下
1
2
3
4
5
6
7
8
9
10
11
12
|
//以当前时间合成图片名称 - (NSString *)getImageNameBaseCurrentTime { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@ "yyyy-MM-dd HH-mm-ss" ]; return [[dateFormatter stringFromDate:[NSDate date]] stringByAppendingString:@ ".JPG" ]; } //以当前时间合成视频名称 - (NSString *)getVideoNameBaseCurrentTime { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@ "yyyy-MM-dd HH-mm-ss" ]; return [[dateFormatter stringFromDate:[NSDate date]] stringByAppendingString:@ ".MOV" ]; } |
有时候需要获取视频的第一帧作为显示, 方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//获取视频的第一帧截图, 返回UIImage //需要导入AVFoundation.h - (UIImage*) getVideoPreViewImageWithPath:(NSURL *)videoPath { AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoPath options:nil]; AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset]; gen.appliesPreferredTrackTransform = YES; CMTime time = CMTimeMakeWithSeconds( 0.0 , 600 ); NSError *error = nil; CMTime actualTime; CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error]; UIImage *img = [[UIImage alloc] initWithCGImage:image]; return img; } |
5. 如何上传?
下面就是上传方法:
我把服务器地址xx掉了, 大家可以改为自己的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
//上传图片和视频 - ( void )uploadImageAndMovieBaseModel:(uploadModel *)model { //获取文件的后缀名 NSString *extension = [model.name componentsSeparatedByString:@ "." ].lastObject; //设置mimeType NSString *mimeType; if ([model.type isEqualToString:@ "image" ]) { mimeType = [NSString stringWithFormat:@ "image/%@" , extension]; } else { mimeType = [NSString stringWithFormat:@ "video/%@" , extension]; } //创建AFHTTPSessionManager AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //设置响应文件类型为JSON类型 manager.responseSerializer = [AFJSONResponseSerializer serializer]; //初始化requestSerializer manager.requestSerializer = [AFHTTPRequestSerializer serializer]; manager.responseSerializer.acceptableContentTypes = nil; //设置timeout [manager.requestSerializer setTimeoutInterval: 20.0 ]; //设置请求头类型 [manager.requestSerializer setValue:@ "form/data" forHTTPHeaderField:@ "Content-Type" ]; //设置请求头, 授权码 [manager.requestSerializer setValue:@ "YgAhCMxEehT4N/DmhKkA/M0npN3KO0X8PMrNl17+hogw944GDGpzvypteMemdWb9nlzz7mk1jBa/0fpOtxeZUA==" forHTTPHeaderField:@ "Authentication" ]; //上传服务器接口 NSString *url = [NSString stringWithFormat:@ "http://xxxxx.xxxx.xxx.xx.x" ]; //开始上传 [manager POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) { NSError *error; BOOL success = [formData appendPartWithFileURL:[NSURL fileURLWithPath:model.path] name:model.name fileName:model.name mimeType:mimeType error:&error]; if (!success) { NSLog(@ "appendPartWithFileURL error: %@" , error); } } progress:^(NSProgress * _Nonnull uploadProgress) { NSLog(@ "上传进度: %f" , uploadProgress.fractionCompleted); } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@ "成功返回: %@" , responseObject); model.isUploaded = YES; [self.uploadedArray addObject:model]; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@ "上传失败: %@" , error); model.isUploaded = NO; }]; } |
这里有事先创建两个可变数组uploadArray, uploadedArray, 一个存放准要上传的内容, 一个存放上传完的内容
在准备上传后做什么操作, 可以检查两个数组的数量是否相等
最后是UIImagePickerController的协议方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
#pragma mark - UIImagePickerDelegate methods - ( void )imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info { [picker dismissViewControllerAnimated:YES completion:nil]; //获取用户选择或拍摄的是照片还是视频 NSString *mediaType = info[UIImagePickerControllerMediaType]; if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) { //获取编辑后的照片 NSLog(@ "获取编辑后的好片" ); UIImage *tempImage = info[UIImagePickerControllerEditedImage]; //将照片存入相册 if (tempImage) { if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { //将照片存入相册 NSLog(@ "将照片存入相册" ); UIImageWriteToSavedPhotosAlbum(tempImage, self, nil, nil); } //获取图片名称 NSLog(@ "获取图片名称" ); NSString *imageName = [self getImageNameBaseCurrentTime]; NSLog(@ "图片名称: %@" , imageName); //将图片存入缓存 NSLog(@ "将图片写入缓存" ); [self saveImage:tempImage toCachePath:[PHOTOCACHEPATH stringByAppendingPathComponent:imageName]]; //创建uploadModel NSLog(@ "创建model" ); uploadModel *model = [[uploadModel alloc] init]; model.path = [PHOTOCACHEPATH stringByAppendingPathComponent:imageName]; model.name = imageName; model.type = @ "image" ; model.isUploaded = NO; //将模型存入待上传数组 NSLog(@ "将Model存入待上传数组" ); [self.uploadArray addObject:model]; } } else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) { if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { //如果是拍摄的视频, 则把视频保存在系统多媒体库中 NSLog(@ "video path: %@" , info[UIImagePickerControllerMediaURL]); ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library writeVideoAtPathToSavedPhotosAlbum:info[UIImagePickerControllerMediaURL] completionBlock:^(NSURL *assetURL, NSError *error) { if (!error) { NSLog(@ "视频保存成功" ); } else { NSLog(@ "视频保存失败" ); } }]; } //生成视频名称 NSString *mediaName = [self getVideoNameBaseCurrentTime]; NSLog(@ "mediaName: %@" , mediaName); //将视频存入缓存 NSLog(@ "将视频存入缓存" ); [self saveVideoFromPath:info[UIImagePickerControllerMediaURL] toCachePath:[VIDEOCACHEPATH stringByAppendingPathComponent:mediaName]]; //创建uploadmodel uploadModel *model = [[uploadModel alloc] init]; model.path = [VIDEOCACHEPATH stringByAppendingPathComponent:mediaName]; model.name = mediaName; model.type = @ "moive" ; model.isUploaded = NO; //将model存入待上传数组 [self.uploadArray addObject:model]; } //[picker dismissViewControllerAnimated:YES completion:nil]; } - ( void )imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker dismissViewControllerAnimated:YES completion:nil]; } |
以上所述是小编给大家介绍的iOS实现视频和图片的上传思路,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:http://www.cnblogs.com/zhouxihi/p/6526304.html