2011-12-08 15 views
10

Estoy utilizando RestKit para impulsar las interacciones con mi servidor web. Intento utilizar el enrutamiento para PUBLICAR un objeto Evento al servidor con una imagen adjunta. El código es el siguiente:RestKit Image Upload

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

Si creo una instancia de RKParams utilizando el objeto de evento en serie, a continuación, añadir los datos de imagen y asignarla como propiedad del RKObjectLoader de params, todas las propiedades se convierten en una cadena serializada masiva. Debe haber una forma de cargar una imagen sin la serialización masiva de cadenas.

También he intentado tener una propiedad NSData que esté mapeada a algún atributo, convirtiendo un UIImage en NSData en el camino, pero RestKit se queja de que no se puede mapear. ¿Alguien ha hecho esto antes?

Respuesta

16

hice algo muy similar y funcionó muy bien. Me di cuenta de que su pregunta es acerca de por qué RKObjectSerializer no funciona de la manera que esperaba, pero tal vez sea algo más con su configuración. Estoy publicando mi código para dar un ejemplo claro de algo que funciona. Dicho esto, después de leer la documentación de RKObjectSerializer, no veo por qué no podría inicializar sus RKParams de esa manera en lugar de configurarlos directamente como hago en mi ejemplo. configuración

Router: configuración

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

Mapping:

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

El mensaje: (aviso ya he construido todos mis params en el bloque de mi objeto es sólo una instancia ficticia para activar el enrutador y el enrutador adecuados).

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

extremo de servidor (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; 
    } 

de respuesta del servidor JSON (nótese el keyPath de "petPhoto" que corresponde a la configuración de mapeo):

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

Delegado:

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

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

Funciona perfectamente! Solo una nota al margen: tratar de delimitar todo hasta "evento" configurando la propiedad rootKeyPath de RKObjectMapping ya no parece funcionar. – Jacob

+0

¿Funciona esto en iOS 6? Sigo recibiendo un "RestKit se le pidió que retransmita una nueva corriente del cuerpo para una solicitud. ¿Posible error de conexión o desafío de autenticación?" –