Загрузка образа RestKit

Я использую RestKit для взаимодействия с моим веб-сервером. Я пытаюсь использовать маршрутизацию для POST объекта Event на сервер с прикрепленным к нему изображением. Код выглядит следующим образом:

  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;
  }];

Если я создам экземпляр RKParams, используя сериализованный объект Event, затем добавлю данные изображения и назначу их как свойство params RKObjectLoader, все свойства станут одной большой сериализованной строкой. Должен быть способ загрузить изображение без массивной сериализации строк.

Я также пытался иметь свойство NSData, которое сопоставляется с некоторым атрибутом, попутно преобразовывая UIImage в NSData, но RestKit жалуется, что его невозможно сопоставить. Кто-нибудь делал это раньше?


person Jacob    schedule 08.12.2011    source источник


Ответы (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 (обратите внимание на keyPath "petPhoto", который соответствует настройке сопоставления):

{
    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;
    }
}
person Michael Peterson    schedule 10.12.2011
comment
Работает отлично! Только одно замечание: попытка ограничить все события, установив свойство rootKeyPath RKObjectMapping, похоже, больше не работает. - person Jacob; 13.12.2011
comment
Это работает в iOS 6? Я продолжаю получать RestKit, которого попросили повторно передать новый поток тела для запроса. Возможная ошибка подключения или проблема аутентификации? - person Kyle Clegg; 28.11.2012