1. 程式人生 > >一步步教你如何上傳頭像

一步步教你如何上傳頭像

上傳頭像這一步幾乎在所有的應用中都會用到,但是博主發現即使是那些工作一年甚至兩年的開發者依然會問這個問題,更別提那些初學者了,雖然網上能找到好多種上傳的方法,但是都存在不同程度的誤差,要麼是不夠詳細,要麼是執行出錯,所以博主今天就把自己常用的一種方法拿出來給大家分享一下。
這裡寫圖片描述

首先說明下:博主上傳採用的是AF3.0,因為博主去掉了專案中的介面,所以,這個Demo中是不能上傳成功的,但是效果會有,看官們只需要把自己的url放進去就可以實現上傳了。具體的跟著博主慢慢往下看:

第一步:觸發操作

  //根據警告知道這個物件在iOS8.3被廢棄了,只是依然可以用,在下篇部落格中,會針對廢棄後的提供的新方法做介紹和使用
UIActionSheet * actionSheet = [[UIActionSheet alloc]initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Take photos", @"Select picture in phone album",nil]; actionSheet.delegate=self; actionSheet.actionSheetStyle = UIActionSheetStyleBlackTranslucent; [actionSheet showInView:self
.view];

第二步:選擇相簿或直接拍照

#pragma mark - 選擇手機拍照上傳或者手機相簿上傳
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex==1) {
        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
        picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        picker.delegate
= self; //設定選擇後的圖片可被編輯 picker.allowsEditing = YES; [self presentViewController:picker animated:YES completion:nil]; } if (buttonIndex==0) { UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera; if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) { UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.delegate = self; //設定拍照後的圖片可被編輯 picker.allowsEditing = YES; picker.sourceType = sourceType; [self presentViewController:picker animated:YES completion:nil]; }else { UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"警告" message:@"請使用真機進行測試" delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil]; [alertView show]; NSLog(@"模擬其中無法開啟照相機,請在真機中使用"); } } }

第三步:選擇一張圖片後

#pragma mark - 當在相簿選擇一張圖片後進入這裡
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

{

    NSString *type = [info objectForKey:UIImagePickerControllerMediaType];

    //當選擇的型別是圖片
    if ([type isEqualToString:@"public.image"])
    {

        //先把圖片轉成NSData
        UIImage* image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
        //調整圖片方向,防止上傳後圖片方向不對
        [self fixOrientation:image];
        //壓縮圖片
        NSData *data = UIImageJPEGRepresentation(image, 0.5);

        //圖片儲存的路徑
        //這裡將圖片放在沙盒的documents資料夾中
        NSString * DocumentsPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
        NSLog(@"圖片儲存路徑:%@",DocumentsPath);
        //檔案管理器
        NSFileManager *fileManager = [NSFileManager defaultManager];

        //把剛剛圖片轉換的data物件拷貝至沙盒中 並儲存為image.png
        [fileManager createDirectoryAtPath:DocumentsPath withIntermediateDirectories:YES attributes:nil error:nil];
        [fileManager createFileAtPath:[DocumentsPath stringByAppendingString:@"/image.png"] contents:data attributes:nil];

        //得到選擇後沙盒中圖片的完整路徑
        NSString *filePath = [[NSString alloc]initWithFormat:@"%@%@",DocumentsPath,@"/image.png"];
        NSLog(@"................%@",filePath);



        //表單請求,上傳檔案
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        manager.requestSerializer = [AFJSONRequestSerializer serializer];//請求
        manager.responseSerializer = [AFHTTPResponseSerializer serializer];//響應
        manager.requestSerializer.timeoutInterval = 8;
        /*
         *這裡需要特別注意一下,因為沒有放具體的上傳地址,所以這個上傳方式是不成功的,但是方法是沒錯的,需要替換成正確的上傳地址
         */
        [manager POST:[NSString stringWithFormat:@"url"] parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
            //將圖片以表單形式上傳
            NSData *data1=[NSData dataWithContentsOfFile:filePath];
            [formData appendPartWithFileData:data1 name:@"headPicFile" fileName:@"headPicFile" mimeType:@"image/png"];

            //關閉相簿介面
            [picker dismissViewControllerAnimated:YES completion:nil];
        }progress:^(NSProgress *uploadProgress){


        }success:^(NSURLSessionDataTask *task, id responseObject) {
            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
            NSLog(@"dic:%@",dic);
            //成功後替換新頭像
            NSData *data1=[NSData dataWithContentsOfFile:filePath];
            headImageView.image = [UIImage imageWithData:data1];

        } failure:^(NSURLSessionDataTask *task, NSError *error) {
            NSLog(@"%@",[error description]);
            NSLog(@"%@",error);
            //因為沒有有效地址,所以肯定是上傳失敗的,為了表現出效果,此處也替換為新頭像
            NSData *data1=[NSData dataWithContentsOfFile:filePath];
            headImageView.image = [UIImage imageWithData:data1];
        }];

    }


}

註釋比較詳細,應該都能看懂吧。在這一步直接就上傳成功了。
第四步:矯正圖片方向,這一步和第三步息息相關,在第三部中呼叫

- (UIImage *)fixOrientation:(UIImage *)aImage {

    // No-op if the orientation is already correct
    if (aImage.imageOrientation == UIImageOrientationUp)
        return aImage;

    // We need to calculate the proper transformation to make the image upright.
    // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
    CGAffineTransform transform = CGAffineTransformIdentity;

    switch (aImage.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;

        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }

    switch (aImage.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;

        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        default:
            break;
    }

    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
                                             CGImageGetBitsPerComponent(aImage.CGImage), 0,
                                             CGImageGetColorSpace(aImage.CGImage),
                                             CGImageGetBitmapInfo(aImage.CGImage));
    CGContextConcatCTM(ctx, transform);
    switch (aImage.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
            break;

        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
            break;
    }

    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}

圖片矯正位置,雖然大家不熟悉上面的程式碼,但是看程式碼也能看看明白是在做什麼,目前是為了實現功能,不必深究,想了解的請自行查詢資料。

第五步:點選取消後,返回原來的介面

#pragma mark - 取消圖片選擇
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{

    NSLog(@"您取消了選擇圖片");
    [picker dismissViewControllerAnimated:YES completion:nil];

}

以上五步就完成了頭像的上傳。
這裡再說一個小知識,也是博主早前在把圖片變為圓時發現的,layer.cornerRadius,怎麼設定這個值才能讓圖片為圓呢?一般很多人都會一個個試,直到無限接近圓,這裡博主告訴大家一個小方法,一般來說頭像的圖片都是正方形,即使是矩形也要擷取的,這裡以正方形為例,只需要設定cornerRadius為正方形長的一半,就好像內切圓的半徑一樣,矩形的話類似,設定短邊的一半即可。