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];

}

猜你喜欢

转载自blog.csdn.net/Keep_Moving31038/article/details/81389059