2011-12-08 10 views
10

Korzystam z narzędzia RestKit do kierowania interakcjami z moim serwerem WWW. Próbuję użyć routingu do POST obiektu Event do serwera z dołączonym obrazem. Kod jest w następujący sposób:Przesyłanie obrazu z programu RestKit

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

Jeśli utworzyć instancję RKParams wykorzystaniem zserializowaną obiekt Event, następnie dodać dane obrazu i przypisać go jako majątku RKObjectLoader na params wszystkie właściwości stać jeden masywny odcinkach ciąg. Musi być sposób na przesłanie obrazu bez masowej serializacji ciągów znaków.

Próbowałem również mieć właściwość NSData, która jest zmapowana do jakiegoś atrybutu, konwertując UIImage na NSData po drodze, ale RestKit skarży się, że nie można go zmapować. Czy ktoś to wcześniej zrobił?

Odpowiedz

16

Zrobiłem coś bardzo podobnego i wszystko działało dobrze. Zdaję sobie sprawę, że twoje pytanie dotyczy tego, dlaczego RKObjectSerializer nie działa tak, jak oczekujesz, ale może jest to coś innego w twojej konfiguracji. Publikuję mój kod, aby dać czysty przykład czegoś, co działa. To powiedziawszy, po przeczytaniu dokumentacji RKObjectSerializer, nie rozumiem, dlaczego nie można zainicjować swoich RKParams w ten sposób, zamiast ustawić je bezpośrednio tak jak ja w moim przykładzie.

Router Setup: Konfiguracja

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

Mapowanie:

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

Post: (zawiadomienie od kiedy buduje się wszystkie moje params w bloku mój obiekt jest po prostu instancja typu dummy, aby uruchomić właściwe trasowanie i program odwzorowujący).

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

Server końcowym (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; 
    } 

Odpowiedź serwera JSON (zwróć uwagę na keypath z "petPhoto", która odpowiada konfiguracji mapowania):

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

Delegat:

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

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

Działa idealnie! Tylko jedna uwaga: próba zaklasyfikowania wszystkiego do "zdarzenia" poprzez ustawienie właściwości rootKeyPath obiektu RKObjectMapping już nie działa. – Jacob

+0

Czy to działa w systemie iOS 6? Wciąż dostaję "RestKit został poproszony o retransmitowanie nowego strumienia treści dla żądania. Możliwy błąd połączenia lub wyzwanie uwierzytelnienia?" –

Powiązane problemy