在objective-c中上传挑选的图像

Posted

技术标签:

【中文标题】在objective-c中上传挑选的图像【英文标题】:upload picked image in objective-c 【发布时间】:2015-09-29 13:13:18 【问题描述】:

我是 Objective-c 的新手。我需要在第一个函数中选择的图像在第二个函数中上传:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 

    UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
    self.imageView.image = chosenImage;

    [picker dismissViewControllerAnimated:YES completion:NULL];



- (IBAction)uploadPic:(UIButton *)sender 
    // COnvert Image to NSData
    NSData *dataImage = UIImageJPEGRepresentation([UIImage imageNamed:@"yourImage"], 1.0f);

//added after editing

    // set your URL Where to Upload Image
    NSString *urlString = @"http://url";

    // set your Image Name
    NSString *filename = @"uploaded_file";

    // Create 'POST' MutableRequest with Data and Other Image Attachment.
    NSMutableURLRequest* request= [[NSMutableURLRequest alloc] init];
    [request setURL:[NSURL URLWithString:urlString]];
    [request setHTTPMethod:@"POST"];
    NSString *boundary = @"---------------------------14737809831466499882746641449";
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
    [request addValue:contentType forHTTPHeaderField: @"Content-Type"];
    NSMutableData *postbody = [NSMutableData data];
    [postbody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [postbody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@.jpg\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]];
    [postbody appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [postbody appendData:[NSData dataWithData:dataImage]];
    [postbody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [request setHTTPBody:postbody];

    // Get Response of Your Request
    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    NSString *responseString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
    NSLog(@"Response  %@",responseString);
//end editing
    

在编辑 cmets 中添加的代码是我用来上传图像的代码

【问题讨论】:

【参考方案1】:

您不应使用UIImageJPEGRepresentationUIImagePNGRepresentation。那些会丢失图像的元数据,使文件变大(或者如果您选择 JPEG 压缩因子使NSData 变小,它会降低图像质量)等等。

我建议您保存UIImagePickerControllerReferenceURL,然后,当用户选择保存图像时,您返回照片框架并检索图像的底层NSData

所以,请务必导入 Photos 框架:

@import Photos;

另外,定义一个属性来捕获 URL:

@property (nonatomic, strong) NSURL *imageReferenceURL;

然后在获取图片的时候捕获这个URL:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
    UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
    self.imageView.image = chosenImage;
    self.imageReferenceURL = info[UIImagePickerControllerReferenceURL];

    [picker dismissViewControllerAnimated:YES completion:nil];

当你去上传图片时,从照片框架中检索原始资产的NSData

- (IBAction)uploadPic:(UIButton *)sender 
    PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[self.imageReferenceURL] options:nil];
    PHAsset *asset = [result firstObject];
    if (asset) 
        PHImageManager *manager = [PHImageManager defaultManager];
        [manager requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) 
            // insert your code for uploading here, referencing the `imageData` here rather than `dataImage`.

            // Or, I might recommend AFNetworking:
            //
            // For example, if your web service was expecting a `multipart/form-data` POST and was
            // going to return a JSON response, you could do something like:

            NSString *urlString = @"http://192.168.0.10/udazz/2.0/2.2/ios/1.0/actions.php?targ=user&subTarg=post&txtComment=123456&txtType=ff";
            NSDictionary *parameters = @@"targ"       : @"user",
                                         @"subTarg"    : @"post",
                                         @"txtComment" : @"123456",
                                         @"txtType"    : @"ff";

            NSURL *fileURL     = info[@"PHImageFileURLKey"];
            NSString *filename = [fileURL lastPathComponent];
            NSString *mimeType = [self mimeTypeForPath:filename];

            AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
            // manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // if response is string rather than JSON, uncomment this line 
            [manager POST:urlString parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) 
                [formData appendPartWithFileData:imageData name:@"userfile" fileName:filename mimeType:mimeType];
             success:^(NSURLSessionDataTask *task, id responseObject) 
                NSLog(@"responseObject = %@", responseObject);
             failure:^(NSURLSessionDataTask *task, NSError *error) 
                NSLog(@"error = %@", error);
            ];
        ];
    

或者,如果您想使用自己的上传代码,只需将其调整为使用 NSURLSession(因为 NSURLConnection 现在已弃用,无论如何您都不应该进行同步网络请求):

- (IBAction)uploadPic:(UIButton *)sender 
    PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[self.imageReferenceURL] options:nil];
    PHAsset *asset = [result firstObject];
    if (asset) 
        PHImageManager *manager = [PHImageManager defaultManager];
        [manager requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) 
            // upload the `imageData`

            NSURL *fileURL = info[@"PHImageFileURLKey"];
            NSString *filename = [fileURL lastPathComponent];
            NSString *mimeType = [self mimeTypeForPath:filename];

            NSString *urlString = @"http://192.168.0.10/udazz/2.0/2.2/ios/1.0/actions.php?targ=user&subTarg=post&txtComment=123456&txtType=ff";

            NSMutableURLRequest* request= [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
            [request setHTTPMethod:@"POST"];
            NSString *boundary = @"---------------------------14737809831466499882746641449";
            NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
            [request addValue:contentType forHTTPHeaderField: @"Content-Type"];
            NSMutableData *postbody = [NSMutableData data];
            [postbody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
            [postbody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@\"\r\n", filename] dataUsingEncoding:NSUTF8StringEncoding]];
            [postbody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimeType] dataUsingEncoding:NSUTF8StringEncoding]];
            [postbody appendData:imageData];
            [postbody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];

            NSURLSessionTask *task = [[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:postbody completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) 
                NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                NSLog(@"Response  %@",responseString);
            ];
            [task resume];
        ];
    

顺便说一下,我以编程方式确定 mime 类型的例程(因为你真的不能只假设图像是 JPEG;它也可能是 PNG 和其他类型)如下:

- (NSString *)mimeTypeForPath:(NSString *)path 
    // get a mime type for an extension using MobileCoreServices.framework

    CFStringRef extension = (__bridge CFStringRef)[path pathExtension];
    CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL);
    assert(UTI != NULL);

    NSString *mimetype = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType));
    assert(mimetype != NULL);

    CFRelease(UTI);

    return mimetype;

如果您需要支持早于 Photos 框架的 iOS 版本,请使用ALAssetsLibrary 获取NSData。如果您需要如何执行此操作的示例(仅当您需要支持 8.0 之前的 iOS 版本时),请告诉我。

【讨论】:

我是 Objective-c 的新手,老实说,我不知道该把代码放在哪里。 @MarianoPelizzari - 不用担心。我扩展了我的代码 sn-p 以使其更清晰。 谢谢。现在,我的代码的哪一部分进入了//upload the imageData here @MarianoPelizzari - 抱歉,我假设您已经有了上传图片的代码。不幸的是,答案完全取决于您的 Web 服务需要如何形成图像上传请求。许多 Web 服务会期望 Content-Typemultipart/form-dataPOST 请求(并且像 AFNetworking 这样的工具大大简化了创建这种复杂类型请求的过程),但是您需要确认,因为有过多的替代品。您还需要 URL、字段名称等详细信息。 我在我的问题中添加了代码,它位于//added after editing//end editing 之间。正如代码所示,我需要上传和图像。你能告诉我我是否可以在你的代码中使用部分代码(或全部),你说//upload the imageData here【参考方案2】:

您正在将选取的图像分配给您的 imageView。因此,您可以使用 UIImageViewimage 属性访问它。

你可以像这样访问:

- (IBAction)uploadPic:(UIButton *)sender

    NSData *dataImage = UIImageJPEGRepresentation(self.imageView.image, 1.0f);
    // Do your stuff here

【讨论】:

【参考方案3】:

我已经在我的演示项目中完成了您的要求。我使用 UIIMagePicker 委托函数选择了图像

@interface ViewController ()

    UIImage *chooseImage;



- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

    NSDate *time = [NSDate date];
    NSDateFormatter* df = [NSDateFormatter new];
    [df setDateFormat:@"ddMMyyyy-hhmmss"];
    NSString *timeString = [df stringFromDate:time];
   NSString *fileName = [NSString stringWithFormat:@"%@", timeString];
    
    chooseImage = info[UIImagePickerControllerEditedImage];
    

    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    documentsDirectoryPath = [paths objectAtIndex:0];
    
    NSLog(@"View Controller Path:%@",documentsDirectoryPath);
    
    
    savedImagePath = [documentsDirectoryPath
                      stringByAppendingPathComponent:[NSString stringWithFormat: @"%@-%d.png", fileName, num]];
    
    num += 1;
    
    NSData *imageData = UIImagePNGRepresentation(chooseImage);
    [imageData writeToFile:savedImagePath atomically:NO];
    
    
    [picker dismissViewControllerAnimated:YES completion:NULL];
    [self displayImage];
    
   

-(void)displayImage

    self.imageView.image = chooseImage;

从那个方法中我调用了另一个函数->displayImage,我用它来在 UIImageView 中显示图像。下面是代码。

【讨论】:

以上是关于在objective-c中上传挑选的图像的主要内容,如果未能解决你的问题,请参考以下文章

Objective-C / Cocoa:上传图像、工作内存和存储

如何通过swift中的alamofire上传从手机中挑选的pdf和图像(任何一个选择的任何一个)文件

通过POST方法以objective-c的文件格式将语音和图像与文本数据一起上传到服务器的最简单方法是啥?

如何在上传到服务器之前减小图像文件大小

如何使用objective-c从CloudKit中的资产字段中检索图像

Flutter - 将图像上传到 Firebase 存储