使用 AFNetworking 和 PHP 从照片库上传选定的图像

Posted

技术标签:

【中文标题】使用 AFNetworking 和 PHP 从照片库上传选定的图像【英文标题】:Uploading selected image from photo library using AFNetworking and PHP 【发布时间】:2014-01-28 08:52:33 【问题描述】:

我正在尝试使用 AFNetworking 上传从照片库中选择的图像,但我有点困惑。一些代码示例直接使用图像数据进行上传,一些代码示例使用文件路径。我想在这里使用 AFNetworking 示例代码:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration 

defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];

NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) 
    if (error) 
        NSLog(@"Error: %@", error);
     else 
        NSLog(@"Success: %@ %@", response, responseObject);
    
];
[uploadTask resume];

但我不知道如何获取从照片库中选择的图像路径。 谁能告诉我如何获取我从照片库中选择的图像路径?

编辑 1: 好的!我找到了以下路径解决方案:

NSString *path = [NSTemporaryDirectory()
                      stringByAppendingPathComponent:@"upload-image.tmp"];
NSData *imageData = UIImageJPEGRepresentation(originalImage, 1.0);
[imageData writeToFile:path atomically:YES];
[self uploadMedia:path];

现在我仍然很困惑,因为我已经在我的服务器上为上传的图像创建了一个文件夹。但是 AFNetworking 如何在不访问任何 service.php 页面的情况下将此图像上传到我的文件夹。只需http://example.com/upload 就够了吗?当我尝试上传时,出现以下错误:

Error:
Error Domain=kCFErrorDomainCFNetwork
Code=303 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 303.)"
UserInfo=0x1175a970 NSErrorFailingURLKey=http://www.olcayertas.com/arendi,
    NSErrorFailingURLStringKey=http://www.olcayertas.com/arendi

编辑 2: 好的。我已设法使用以下代码解决错误:

-(void)uploadMedia:(NSString*)filePath 
    NSURLSessionConfiguration *configuration =
    [NSURLSessionConfiguration defaultSessionConfiguration];

    AFURLSessionManager *manager =
        [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

    manager.responseSerializer = [AFHTTPResponseSerializer serializer];

    NSURL *requestURL = 
        [NSURL URLWithString:@"http://www.olcayertas.com/fileUpload.php"];
    NSMutableURLRequest *request = 
        [NSMutableURLRequest requestWithURL:requestURL];

    [request setHTTPMethod:@"POST"];

    NSURL *filePathURL = [NSURL fileURLWithPath:filePath];

    NSURLSessionUploadTask *uploadTask =
        [manager uploadTaskWithRequest:request
                      fromFile:filePathURL progress:nil
             completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) 
                 if (error) 
                     NSLog(@"Error: %@", error);
                  else 
                     NSLog(@"Success: %@ %@", response, responseObject);
                 
             ];

    [uploadTask resume];

我在服务器端使用以下 PHP 代码上传文件:

<?php header('Content-Type: text/plain; charset=utf-8');

try 

    // Undefined | Multiple Files | $_FILES Corruption Attack
    // If this request falls under any of them, treat it invalid.
    if (!isset($_FILES['upfile']['error']) ||
        is_array($_FILES['upfile']['error'])) 
        throw new RuntimeException('Invalid parameters.');
        error_log("File Upload: Invalid parameters.", 3, "php2.log");
    

    // Check $_FILES['upfile']['error'] value.
    switch ($_FILES['upfile']['error']) 
        case UPLOAD_ERR_OK:
            break;
        case UPLOAD_ERR_NO_FILE:
            throw new RuntimeException('No file sent.');
            error_log("File Upload: No file sent.", 3, "php2.log");
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            throw new RuntimeException('Exceeded filesize limit.');
            error_log("File Upload: Exceeded filesize limit.", 3, "php2.log");
        default:
            throw new RuntimeException('Unknown errors.');
            error_log("File Upload: Unknown errors.", 3, "php2.log");
    

    // You should also check filesize here.
    if ($_FILES['upfile']['size'] > 1000000) 
        throw new RuntimeException('Exceeded filesize limit.');
        error_log("File Upload: Exceeded filesize limit.", 3, "php2.log");
    

    // DO NOT TRUST $_FILES['upfile']['mime'] VALUE !!
    // Check MIME Type by yourself.
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    if (false === $ext = array_search(
        $finfo->file($_FILES['upfile']['tmp_name']),
        array(
            'jpg' => 'image/jpeg',
            'png' => 'image/png',
            'gif' => 'image/gif',
        ), true)) 
        throw new RuntimeException('Invalid file format.');
        error_log("File Upload: Invalid file format.", 3, "php2.log");
    

    // You should name it uniquely.
    // DO NOT USE $_FILES['upfile']['name'] WITHOUT ANY VALIDATION !!
    // On this example, obtain safe unique name from its binary data.
    if (!move_uploaded_file($_FILES['upfile']['tmp_name'], sprintf('./uploads/%s.%s', sha1_file($_FILES['upfile']['tmp_name']), $ext))) 
        throw new RuntimeException('Failed to move uploaded file.');
        error_log("File Upload: Failed to move uploaded file.", 3, "php2.log");
    

    echo 'File is uploaded successfully.';
    error_log("File Upload: File is uploaded successfully.", 3, "php2.log");

 catch (RuntimeException $e) 
    echo $e->getMessage();
    error_log("File Upload: " . $e->getMessage(), 3, "php2.log");


?>

编辑 3: 现在我已经了解了 $_FILES 的工作原理。当我运行我的代码时,我收到了成功消息,但文件没有上传到服务器。知道可能出了什么问题吗?

【问题讨论】:

你有没有让这个工作?我现在正在遇到一模一样的问题。为什么这么难找到答案?我原以为成千上万的人想要将图像上传到那里的网站。而不是使用像解析这样的网站。 是的,我有,我会尽快用工作代码更新问题。但我对我目前的解决方案并不满意。它看起来很脆弱而且不安全。 目前我还没有达到我最初的目标,所以我正在做一个工作。 干得好!可以给我看看?如果您不想给我看,请不要担心。 请在完成后通知我好吗?因为它正在驱使我绕过弯道?你能指出我目前的任何链接或任何东西吗? 【参考方案1】:

Afnetworking 有一个通过多部分发布的上传方法。

NSMutableURLRequest *request = [httpClient multipartFormRequestWithMethod:@"POST" path:@"/v1/api" parameters:parameters constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) 
    [formData appendPartWithFileData:imageData name:@"filename" fileName:@"file.jpg" mimeType:@"image/jpeg"];
];

imageData 在哪里:

UIImage *originalImage = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *imageData = UIImageJPEGRepresentation(originalImage, 1.0);

【讨论】:

【参考方案2】:

使用以下代码

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
[picker dismissViewControllerAnimated:YES completion:nil];
UIImage *image = info[UIImagePickerControllerOriginalImage];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc]init];
[parameters setObject:@"imageUploaing" forKey:@"firstKey"];
NSString *fileName = [NSString stringWithFormat:@"%ld%c%c.jpg", (long)[[NSDate date] timeIntervalSince1970], arc4random_uniform(26) + 'a', arc4random_uniform(26) + 'a'];

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSData *data = UIImageJPEGRepresentation(image, 0.5);
[manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) 
    [formData appendPartWithFileData:data name:@"image" fileName:fileName mimeType:@"image/jpeg"];
 success:^(AFHTTPRequestOperation *operation, id responseObject) 
    NSLog(@"Success: %@", responseObject);
 failure:^(AFHTTPRequestOperation *operation, NSError *error) 
    NSLog(@"Error: %@", error);
];


【讨论】:

我仍然需要有一个 service.php 页面来获取这个文件吗?【参考方案3】:

虽然还有其他上传图片的方法,如果你想使用你描述的方法,那么在选择图片后你可以得到它的URL,如下所示:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 
    NSURL *imageURL = [info valueForKey:UIImagePickerControllerReferenceURL];

这是假设您使用UIImagePickerController 选择图像。

【讨论】:

以上是关于使用 AFNetworking 和 PHP 从照片库上传选定的图像的主要内容,如果未能解决你的问题,请参考以下文章

从网络下载图像到照片应用程序 AFNetworking 3

AFNetworking 和集合视图阻塞主线程

使用 afnetworking 删除照片

使用 AFNetworking 2.0 加载图像

AFNetworking 使用 NSMutableURLRequest 上传?

PHP REST 服务中的 JSON 格式问题从 AFNetworking 2.0 接收 POST