轉(zhuǎn)載:https://www.cnblogs.com/zhouxihi/p/6526304.html
以下純轉(zhuǎn)載上述地址老鐵的文章,只為本人記載后續(xù)使用,詳情參考上邊連接!!!
iOS實(shí)現(xiàn)視頻和圖片的上傳
關(guān)于iOS如何實(shí)現(xiàn)視頻和圖片的上傳, 我們先理清下思路
思路:
1. 如何獲取圖片?
2. 如何獲取視頻?
3. 如何把圖片存到緩存路徑中?
4. 如何把視頻存到緩存路徑中?
5. 如何上傳?
接下來(lái), 我們按照上面的思路一步一步實(shí)現(xiàn)
首先我們新建一個(gè)類(lèi), 用來(lái)儲(chǔ)存每一個(gè)要上傳的文件uploadModel.h
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">#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</pre>
1. 如何獲取圖片?
從相冊(cè)選擇 或者 拍照,
這部分可以用UIImagePickerController來(lái)實(shí)現(xiàn)
代碼如下:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">- (void)actionPhoto {
UIAlertController *alertController = \
[UIAlertController alertControllerWithTitle:@"" message:@"上傳照片" preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *photoAction = \
[UIAlertAction actionWithTitle:@"從相冊(cè)選擇" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"從相冊(cè)選擇");
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];
}</pre>
2. 如果獲取視頻?
從相冊(cè)選擇 或者 拍攝
這部分也可以用UIImagePickerController來(lái)實(shí)現(xiàn)
代碼:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">- (void)actionVideo {
UIAlertController *alertController = \
[UIAlertController alertControllerWithTitle:@"" message:@"上傳視頻" preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *photoAction = \
[UIAlertAction actionWithTitle:@"從視頻庫(kù)選擇" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"從視頻庫(kù)選擇");
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];
}</pre>
3, 關(guān)于緩存, 如何把照片存入緩存目錄?
這部分我們先考慮緩存目錄, 一般存在Document 或者 Temp里面
我們給圖片和視頻各創(chuàng)建一個(gè)緩存目錄:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">#define PHOTOCACHEPATH [NSTemporaryDirectory() stringByAppendingPathComponent:@"photoCache"]
define VIDEOCACHEPATH [NSTemporaryDirectory() stringByAppendingPathComponent:@"videoCache"]</pre>
把UIImage存入緩存的方法:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">//將Image保存到緩存路徑中
-
(void)saveImage:(UIImage *)image toCachePath:(NSString *)path {
NSFileManager *fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:PHOTOCACHEPATH]) {
NSLog(@"路徑不存在, 創(chuàng)建路徑"); [fileManager createDirectoryAtPath:PHOTOCACHEPATH withIntermediateDirectories:YES attributes:nil error:nil];
} else {
NSLog(@"路徑存在");
} //[UIImagePNGRepresentation(image) writeToFile:path atomically:YES];
[UIImageJPEGRepresentation(image, 1) writeToFile:path atomically:YES];
}</pre>
4. 如何把視頻存入緩存?
把視頻存入緩存的方法:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">//將視頻保存到緩存路徑中
-
(void)saveVideoFromPath:(NSString *)videoPath toCachePath:(NSString *)path {
NSFileManager *fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:VIDEOCACHEPATH]) {
NSLog(@"路徑不存在, 創(chuàng)建路徑"); [fileManager createDirectoryAtPath:VIDEOCACHEPATH withIntermediateDirectories:YES attributes:nil error:nil];
} else {
NSLog(@"路徑存在");
}
NSError *error;
[fileManager copyItemAtPath:videoPath toPath:path error:&error]; if (error) {NSLog(@"文件保存到緩存失敗");
}
}</pre>
從緩存獲取圖片的方法:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">//從緩存路徑獲取照片
-
(UIImage *)getImageFromPath:(NSString *)path {
NSFileManager *fileManager = [NSFileManager defaultManager]; if ([fileManager fileExistsAtPath:path]) { return [UIImage imageWithContentsOfFile:path];
} return nil;
}</pre>
上傳圖片和視頻的時(shí)候我們一般會(huì)利用當(dāng)前時(shí)間給文件命名, 方法如下
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">//以當(dāng)前時(shí)間合成圖片名稱(chēng)
-
(NSString *)getImageNameBaseCurrentTime {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH-mm-ss"]; return [[dateFormatter stringFromDate:[NSDate date]] stringByAppendingString:@".JPG"];
} //以當(dāng)前時(shí)間合成視頻名稱(chēng) -
(NSString *)getVideoNameBaseCurrentTime {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH-mm-ss"]; return [[dateFormatter stringFromDate:[NSDate date]] stringByAppendingString:@".MOV"];
}</pre>
有時(shí)候需要獲取視頻的第一幀作為顯示, 方法如下:
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">//獲取視頻的第一幀截圖, 返回UIImage //需要導(dǎo)入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;
}</pre>
5. 如何上傳?
下面就是上傳方法:
我把服務(wù)器地址xx掉了, 大家可以改為自己的
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">//上傳圖片和視頻
-
(void)uploadImageAndMovieBaseModel:(uploadModel *)model { //獲取文件的后綴名
NSString *extension = [model.name componentsSeparatedByString:@"."].lastObject; //設(shè)置mimeType
NSString *mimeType; if ([model.type isEqualToString:@"image"]) {mimeType = [NSString stringWithFormat:@"image/%@", extension];
} else {
mimeType = [NSString stringWithFormat:@"video/%@", extension];
} //創(chuàng)建AFHTTPSessionManager
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //設(shè)置響應(yīng)文件類(lèi)型為JSON類(lèi)型
manager.responseSerializer = [AFJSONResponseSerializer serializer]; //初始化requestSerializer
manager.requestSerializer = [AFHTTPRequestSerializer serializer];manager.responseSerializer.acceptableContentTypes = nil; //設(shè)置timeout
[manager.requestSerializer setTimeoutInterval:20.0]; //設(shè)置請(qǐng)求頭類(lèi)型
[manager.requestSerializer setValue:@"form/data" forHTTPHeaderField:@"Content-Type"]; //設(shè)置請(qǐng)求頭, 授權(quán)碼
[manager.requestSerializer setValue:@"YgAhCMxEehT4N/DmhKkA/M0npN3KO0X8PMrNl17+hogw944GDGpzvypteMemdWb9nlzz7mk1jBa/0fpOtxeZUA==" forHTTPHeaderField:@"Authentication"]; //上傳服務(wù)器接口
NSString *url = [NSString stringWithFormat:@"http://xxxxx.xxxx.xxx.xx.x"]; //開(kāi)始上傳
[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(@"上傳進(jìn)度: %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;
}];
}</pre>
這里有事先創(chuàng)建兩個(gè)可變數(shù)組uploadArray, uploadedArray, 一個(gè)存放準(zhǔn)要上傳的內(nèi)容, 一個(gè)存放上傳完的內(nèi)容
在準(zhǔn)備上傳后做什么操作, 可以檢查兩個(gè)數(shù)組的數(shù)量是否相等
最后是UIImagePickerController的協(xié)議方法
<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; word-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">#pragma mark - UIImagePickerDelegate methods
-
(void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {[picker dismissViewControllerAnimated:YES completion:nil]; //獲取用戶(hù)選擇或拍攝的是照片還是視頻
NSString *mediaType = info[UIImagePickerControllerMediaType]; if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) { //獲取編輯后的照片
NSLog(@"獲取編輯后的好片");
UIImage *tempImage = info[UIImagePickerControllerEditedImage]; //將照片存入相冊(cè)
if (tempImage) { if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { //將照片存入相冊(cè)
NSLog(@"將照片存入相冊(cè)");
UIImageWriteToSavedPhotosAlbum(tempImage, self, nil, nil);
} //獲取圖片名稱(chēng)
NSLog(@"獲取圖片名稱(chēng)");
NSString *imageName = [self getImageNameBaseCurrentTime];
NSLog(@"圖片名稱(chēng): %@", imageName); //將圖片存入緩存
NSLog(@"將圖片寫(xiě)入緩存");
[self saveImage:tempImage
toCachePath:[PHOTOCACHEPATH stringByAppendingPathComponent:imageName]]; //創(chuàng)建uploadModel
NSLog(@"創(chuàng)建model");
uploadModel *model = [[uploadModel alloc] init];model.path = [PHOTOCACHEPATH stringByAppendingPathComponent:imageName]; model.name = imageName; model.type = @"image"; model.isUploaded = NO; //將模型存入待上傳數(shù)組 NSLog(@"將Model存入待上傳數(shù)組"); [self.uploadArray addObject:model]; }
} else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) { if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { //如果是拍攝的視頻, 則把視頻保存在系統(tǒng)多媒體庫(kù)中
NSLog(@"video path: %@", info[UIImagePickerControllerMediaURL]);ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library writeVideoAtPathToSavedPhotosAlbum:info[UIImagePickerControllerMediaURL] completionBlock:^(NSURL *assetURL, NSError *error) { if (!error) { NSLog(@"視頻保存成功"); } else { NSLog(@"視頻保存失敗"); } }]; } //生成視頻名稱(chēng) NSString *mediaName = [self getVideoNameBaseCurrentTime]; NSLog(@"mediaName: %@", mediaName); //將視頻存入緩存 NSLog(@"將視頻存入緩存"); [self saveVideoFromPath:info[UIImagePickerControllerMediaURL] toCachePath:[VIDEOCACHEPATH stringByAppendingPathComponent:mediaName]]; //創(chuàng)建uploadmodel uploadModel *model = [[uploadModel alloc] init]; model.path = [VIDEOCACHEPATH stringByAppendingPathComponent:mediaName]; model.name = mediaName; model.type = @"moive"; model.isUploaded = NO; //將model存入待上傳數(shù)組
[self.uploadArray addObject:model];
} //[picker dismissViewControllerAnimated:YES completion:nil];
} - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:nil];
}</pre>