2013-02-16 24 views
6

JSON kullanarak bir sunucuya görüntü yüklemek için bu işlevi kullanıyorum. Bunu yapmak için önce görüntüyü NSData'a ve daha sonra kullanarak NSString'a dönüştürüyorum. Yöntem, görüntü çok büyük olmadığında iyi çalışır, ancak 2Mb resmi yüklemeye çalıştığımda, çöker.Base64 ve JSON kullanarak büyük resimler yükleme

sorun sunucu didReceiveResponse yöntem (null) döndürür didReceiveData yanı sıra denir halde Resmimi almaz olmasıdır. İlk başta bir zaman aşımı sorunu olduğunu düşündüm ama 1000.0'a ayarladım bile hala çalışmıyor. Herhangi bir fikir? Zaman ayırdığın için teşekkürler!

- (void) imageRequest { 

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.myurltouploadimage.com/services/v1/upload.json"]]; 

    NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    NSString *path = [NSString stringWithFormat:@"%@/design%i.png",docDir, designNum]; 
    NSLog(@"%@",path); 

    NSData *imageData = UIImagePNGRepresentation([UIImage imageWithContentsOfFile:path]); 
    [Base64 initialize]; 
    NSString *imageString = [Base64 encode:imageData]; 

    NSArray *keys = [NSArray arrayWithObjects:@"design",nil]; 
    NSArray *objects = [NSArray arrayWithObjects:imageString,nil]; 
    NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; 

    NSError *error; 
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:kNilOptions error:&error]; 

    [request setHTTPMethod:@"POST"]; 
    [request setValue:[NSString stringWithFormat:@"%d",[jsonData length]] forHTTPHeaderField:@"Content-Length"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
    [request setHTTPBody:jsonData]; 

    [[NSURLConnection alloc] initWithRequest:request delegate:self]; 

    NSLog(@"Image uploaded"); 

} 

- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 

    NSLog(@"didReceiveResponse"); 

} 

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 

    NSLog(@"%@",[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]); 

} 
+0

en azından, url denir olmadığını görmek için php web sayfasındaki herhangi günlükleri eklediniz mi? bir dosya günlüğü veya sql günlüğü gibi mi? – Vinzius

+1

Aslında, sunucu tarafındaki programcı, web sitesi herhangi bir veri alırsa, yanıtın her zaman geri döndüğünü söyledi. Sonuç olarak benim isteğim, talebi bile almadı. –

+1

Yan yana: değişmezleri kullanmak işleri daha kolay/daha açık hale getirir: 'NSDictionary * jsonDictionary = @ {@" tasarım ": imageString};' – zaph

cevap

8

Sonunda, Base64 görüntüsünü daha küçük alt dizelere ayırarak yüklemeye karar verdim. Bunu yapmak için ve birçok NSURLConnections'a ihtiyaç duyduğumda, her bağlantı için bir etiket veren TagConnection adında bir alt sınıf oluşturdum, böylece aralarında olası bir karışıklık olmadı.

Daha sonra, herhangi bir işlevden erişmek amacıyla MyViewController numaralı TagConnection özelliğini oluşturdum. Gördüğünüz gibi, -startAsyncLoad:withTag: işlevi, tüm sunucu ve TagConnection ve -connection:didReceiveData: bir sunucudan yanıt aldığınızda onu siler.

-uploadImage işlevine başvurulursa, önce görüntü dizeye dönüştürülür ve ardından parçalara bölünür ve parçaları JSON isteğinin içine koyar. Değişken ofset, dizi uzunluğundan daha büyük olana kadar çağrılır, bu da tüm parçaların yüklendiği anlamına gelir.

Ayrıca, her seferinde sunucu yanıtını her seferinde kontrol ederek ve yalnızca başarılı olduğunda -uploadImage işlevini çağırarak her bir parçanın başarıyla yüklendiğini ispatlayabilirsiniz.

Umarım bu yararlı bir cevap olmuştur. Teşekkürler.

TagConnection.h

@interface TagConnection : NSURLConnection { 
    NSString *tag; 
} 

@property (strong, nonatomic) NSString *tag; 

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately tag:(NSString*)tag; 

@end 

TagConnection.m

#import "TagConnection.h" 

@implementation TagConnection 

@synthesize tag; 

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately tag:(NSString*)tag { 
    self = [super initWithRequest:request delegate:delegate startImmediately:startImmediately]; 

    if (self) { 
     self.tag = tag; 
    } 
    return self; 
} 

- (void)dealloc { 
    [tag release]; 
    [super dealloc]; 
} 

@end 

MyViewController.h

#import "TagConnection.h" 

@interface MyViewController : UIViewController 

@property (strong, nonatomic) TagConnection *conn; 

MyViewController.m

#import "MyViewController.h" 

@interface MyViewController() 

@end 

@synthesize conn; 

bool stopSending = NO; 
int chunkNum = 1; 
int offset = 0; 

- (IBAction) uploadImageButton:(id)sender { 

    [self uploadImage]; 

} 

- (void) startAsyncLoad:(NSMutableURLRequest *)request withTag:(NSString *)tag { 

    self.conn = [[[TagConnection alloc] initWithRequest:request delegate:self startImmediately:YES tag:tag] autorelease]; 

} 

- (void) uploadImage { 

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.mywebpage.com/upload.json"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:1000.0]; 

    NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    NSString *path = [NSString stringWithFormat:@"%@/design%i.png", docDir, designNum]; 
    NSLog(@"%@",path); 

    NSData *imageData = UIImagePNGRepresentation([UIImage imageWithContentsOfFile:path]); 
    [Base64 initialize]; 
    NSString *imageString = [Base64 encode:imageData]; 

    NSUInteger length = [imageString length]; 
    NSUInteger chunkSize = 1000; 

    NSUInteger thisChunkSize = length - offset > chunkSize ? chunkSize : length - offset; 
    NSString *chunk = [imageString substringWithRange:NSMakeRange(offset, thisChunkSize)]; 
    offset += thisChunkSize; 

    NSArray *keys = [NSArray arrayWithObjects:@"design",@"design_id",@"fragment_id",nil]; 
    NSArray *objects = [NSArray arrayWithObjects:chunk,@"design_id",[NSString stringWithFormat:@"%i", chunkNum],nil]; 
    NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; 

    NSError *error; 
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:kNilOptions error:&error]; 

    [request setHTTPMethod:@"POST"]; 
    [request setValue:[NSString stringWithFormat:@"%d",[jsonData length]] forHTTPHeaderField:@"Content-Length"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
    [request setHTTPBody:jsonData]; 

    [self startAsyncLoad:request withTag:[NSString stringWithFormat:@"tag%i",chunkNum]]; 

    if (offset > length) { 
     stopSending = YES; 
    } 

} 

- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 

    NSError *error; 
    NSArray *responseData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; 
    if (!responseData) { 
     NSLog(@"Error parsing JSON: %@", error); 
    } else { 
     if (stopSending == NO) { 
      chunkNum++; 
      [self.conn cancel]; 
      self.conn = nil; 
      [self uploadImage]; 
     } else { 
      NSLog(@"---------Image sent---------"); 
     } 
    } 

} 

@end 
+1

Sunucu tarafı kodu için de yardım edebilir misiniz? Bunu php tarafında yapamam! –

+0

Üzgünüm, ama bu bana bağlı değil. –

2

bu son seçenek olduğunu sanmıyorum Lütfen, bu benim gözlem:

İşte benim geçerli kod var.

Bu NSData'yı tam Veri yerine parçalar halinde göndermelisiniz. YouTube Video Uploading vakasında böyle bir metodoloji gördüm. Birçok NSData'nın Chunks'indeki Büyük NSData (Video Dosyasının NSData) kümesini gönderdiler.

Büyük veriyi yüklemek için aynı metodolojiyi kullanırlar.

Youtube veri yükleme API'sı hakkında Google'a başvurmanız gerekir. Ayrıca, YouTube Yükleyici Kullanımları yöntemini de araştırmanız gerekir.

Umarım size yardımcı olabilir.

+0

Bunun gibi bir şey: http://stackoverflow.com/questions/2899020/split-nsdata-objects-into-other-nsdata-objects-with-a-given-size –

İlgili konular