RestKit 图片上传

Posted

技术标签:

【中文标题】RestKit 图片上传【英文标题】:RestKit Image Upload 【发布时间】:2012-01-16 07:31:15 【问题描述】:

我正在使用 RestKit 来驱动与我的 Web 服务器的交互。我正在尝试使用路由将事件对象发布到服务器,并附有图像。代码如下:

  RKObjectManager *manager = [RKObjectManager sharedManager];

  RKObjectMapping *map = [self eventMapping];
  manager.serializationMIMEType = RKMIMETypeFormURLEncoded;
  map.rootKeyPath = @"event";
  [manager.mappingProvider setSerializationMapping:map forClass:[Event class]];
  [manager.router routeClass:[Event class] toResourcePath:@"/v1/events.json" forMethod:RKRequestMethodPOST];

  [manager postObject:event delegate:self block:^(RKObjectLoader *loader)
    RKObjectMapping *serMap = [[[RKObjectManager sharedManager] mappingProvider] serializationMappingForClass:[Event class]];
    NSError *error = nil;
    NSDictionary *d = [[RKObjectSerializer serializerWithObject:event mapping:serMap] serializedObject:&error];

    RKParams *p = [RKParams paramsWithDictionary:d];
    [p setData:[event imageData] MIMEType:@"image/jpeg" forParam:@"image"];
    loader.params = p;
  ];

如果我使用序列化的 Event 对象创建 RKParams 的实例,然后添加图像数据并将其分配为 RKObjectLoader 的 params 属性,则所有属性都成为一个庞大的序列化字符串。必须有一种方法可以在没有大量字符串序列化的情况下上传图片。

我也尝试过拥有一个映射到某个属性的 NSData 属性,一路将 UIImage 转换为 NSData,但 RestKit 抱怨它无法映射。以前有人做过吗?

【问题讨论】:

【参考方案1】:

我做了一些非常相似的事情,结果很好。我意识到您的问题是关于为什么 RKObjectSerializer 没有按您期望的方式工作,但也许它与您的设置有关。我发布我的代码是为了给出一个有效的例子。也就是说,在阅读了 RKObjectSerializer 文档之后,我不明白为什么不能像我在示例中那样直接设置 RKParams 而是以这种方式初始化它们。

路由器设置:

RKObjectManager *objectManager = [RKObjectManager objectManagerWithBaseURL:kApiUrlBase];
[objectManager.router routeClass:[PAPetPhoto class] toResourcePath:@"/pet/uploadPhoto" forMethod:RKRequestMethodPOST];

映射设置:

RKObjectMapping *papetPhotoMapping = [RKObjectMapping mappingForClass:[PAPetPhoto class]];
[papetPhotoMapping mapKeyPath:@"id" toAttribute:@"identifier"];
[papetPhotoMapping mapAttributes:@"accountId", @"petId", @"photoId", @"filename", @"contentType", nil];
[objectManager.mappingProvider addObjectMapping:papetPhotoMapping];
[objectManager.mappingProvider setSerializationMapping:[papetPhotoMapping inverseMapping] forClass:[PAPetPhoto class]];
[objectManager.mappingProvider setMapping:papetPhotoMapping forKeyPath:@"petPhoto"];

帖子:(请注意,由于我在块中构建了所有参数,因此我的对象只是一个虚拟实例,用于触发正确的路由和映射器)。

    PAPetPhoto *photo = [[PAPetPhoto alloc] init];
    [[RKObjectManager sharedManager] postObject:photo delegate:self block:^(RKObjectLoader *loader)

        RKParams* params = [RKParams params];
        [params setValue:pet.accountId forParam:@"accountId"];
        [params setValue:pet.identifier forParam:@"petId"];
        [params setValue:_photoId forParam:@"photoId"];
        [params setValue:_isThumb ? @"THUMB" : @"FULL" forParam:@"photoSize"];
        [params setData:data MIMEType:@"image/png" forParam:@"image"];

        loader.params = params;
    ];

服务器端点(Java、Spring MVC)

    @RequestMapping(value = "/uploadPhoto", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> handleFormUpload(@RequestParam("accountId") String accountId,
                                    @RequestParam("petId") String petId,
                                    @RequestParam("photoId") String photoId,
                                    @RequestParam("photoSize") PhotoSizeEnum photoSize,
                                    @RequestParam("image") Part image) throws IOException 

        if (log.isTraceEnabled()) 
            log.trace("uploadPhoto. accountId=" + accountId + " petId=" + petId + " photoId=" + photoId + " photoSize=" + photoSize);

        PetPhoto petPhoto = petDao.savePetPhoto(accountId, petId, photoId, photoSize, image);

        Map<String, Object> map = GsonUtils.wrapWithKeypath(petPhoto, "petPhoto");
        return map;
    

服务器响应 JSON(注意与映射设置对应的“petPhoto”的 keyPath):


    petPhoto =     
        accountId = 4ebee3469ae2d8adf983c561;
        contentType = "image/png";
        filename = "4ebee3469ae2d8adf983c561_4ec0983d036463d900841f09_3FED4959-1042-4D8B-91A8-76AA873851A3";
        id = 4ee2e80203646ecd096d5201;
        petId = 4ec0983d036463d900841f09;
        photoId = "3FED4959-1042-4D8B-91A8-76AA873851A3";
    ;

代表:

- (void) objectLoader:(RKObjectLoader*)objectLoader didLoadObject:(id)object 

    if ([objectLoader wasSentToResourcePath:@"/pet/uploadPhoto"]) 
       PAPetPhoto *photo = (PAPetPhoto*)object;
    

【讨论】:

完美运行!只是一个侧面说明:试图通过设置 RKObjectMapping 的 rootKeyPath 属性将所有内容都限定为“事件”似乎不再起作用了。 这在 ios 6 中有效吗?我不断收到“RestKit 被要求重新传输请求的新正文流。可能的连接错误或身份验证挑战?”

以上是关于RestKit 图片上传的主要内容,如果未能解决你的问题,请参考以下文章

新手 想问下,上传图片到FastDfs后,如何在该虚拟机下找到上传的图片

怎样向网站上传图片

ASP.NET上传控件上传图片

我本地的图片怎么上传上去?就是图片要弄地址?

PHP Fckeditor 上传图片的问题

php 在多个上传图片时 怎么获取 要上传的图片宽高