web-dev-qa-db-fra.com

iOS: Télécharger l'image à partir de l'URL et enregistrer dans l'appareil

J'essaie de télécharger l'image depuis l'url http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg

J'utilise le code suivant, mais l'image n'est pas enregistrée dans l'appareil. Je veux savoir ce que je fais mal.

 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg"]];
 [NSURLConnection connectionWithRequest:request delegate:self];

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
 NSString *documentsDirectory = [paths objectAtIndex:0];
 NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:@"pkm.jpg"];
 NSData *thedata = NULL;
 [thedata writeToFile:localFilePath atomically:YES];

 UIImage *img = [[UIImage alloc] initWithData:thedata];
44
User97693321

Si vous définissez theData sur nil, qu'espérez-vous qu'il écrive sur le disque?

Ce que vous pouvez utiliser, c'est NSData* theData = [NSData dataWithContentsOfURL:yourURLHere]; pour charger les données à partir du disque, puis enregistrez-les à l'aide de writeToFile:atomically:. Si vous avez besoin de plus de contrôle sur le processus de chargement ou si vous l’avez en arrière-plan, consultez la documentation de NSURLConnection et le guide associé.

35
Alfonso

Il se trouve que j'ai exactement ce que vous recherchez.

Obtenir l'image de l'URL

-(UIImage *) getImageFromURL:(NSString *)fileURL {
    UIImage * result;

    NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]];
    result = [UIImage imageWithData:data];

    return result;
}

Enregistrer l'image

-(void) saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
    if ([[extension lowercaseString] isEqualToString:@"png"]) {
        [UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]] options:NSAtomicWrite error:nil];
    } else if ([[extension lowercaseString] isEqualToString:@"jpg"] || [[extension lowercaseString] isEqualToString:@"jpeg"]) {
        [UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]] options:NSAtomicWrite error:nil];
    } else {
        NSLog(@"Image Save Failed\nExtension: (%@) is not recognized, use (PNG/JPG)", extension);
    }
}

Charger une image

-(UIImage *) loadImage:(NSString *)fileName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
    UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.%@", directoryPath, fileName, extension]];

    return result;
}

Comment

//Definitions
NSString * documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

//Get Image From URL
UIImage * imageFromURL = [self getImageFromURL:@"http://www.yourdomain.com/yourImage.png"];

//Save Image to Directory
[self saveImage:imageFromURL withFileName:@"My Image" ofType:@"png" inDirectory:documentsDirectoryPath];

//Load Image From Directory
UIImage * imageFromWeb = [self loadImage:@"My Image" ofType:@"png" inDirectory:documentsDirectoryPath];
101

Ceci est le code pour télécharger l'image à partir de l'URL et enregistrer cette image dans l'appareil. This est le lien de référence.

 NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg"]];
 [NSURLConnection connectionWithRequest:request delegate:self];

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
 NSString *documentsDirectory = [paths objectAtIndex:0];
 NSString *localFilePath = [documentsDirectory stringByAppendingPathComponent:@"pkm.jpg"];
 NSData *thedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://a3.twimg.com/profile_images/414797877/05052008321_bigger.jpg"]];
 [thedata writeToFile:localFilePath atomically:YES];
9
User97693321

Obtenir l'image de l'URL

-(UIImage *) getImageFromURL:(NSString *)fileURL {
    UIImage * result;

    NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]];
    result = [UIImage imageWithData:data];

    return result;
}

Cela a très bien fonctionné pour moi, mais j'ai rencontré des problèmes de mémoire avec CFData (magasin). Corrigé avec un autoreleasepool:

 -(UIImage *) getImageFromURL:(NSString *)fileURL {
    @autoreleasepool {
     UIImage * result;

     NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileURL]];
     result = [UIImage imageWithData:data];

     return result;
    }
 }
4
mark.ed
-(IBAction)BtnDwn:(id)sender
{
  [self.actvityIndicator startAnimating];

  NSURL *URL = [NSURL URLWithString:self.dataaArray];
  NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  NSURLSession *session = [NSURLSession sharedSession];

  NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
   {

      NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
      NSURL *documentsDirectoryURL = [NSURL fileURLWithPath:documentsPath];
      NSURL *documentURL = [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
      BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:[documentURL path]];

      if (exists)
      {
         NSLog(@"not created");
         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Download"
                                                    message:@"sory,file already exists"
                                                   delegate:nil
                                          cancelButtonTitle:@"cancel"
                                          otherButtonTitles:nil];
         [alert show];
      }
      else
      { 
         [[NSFileManager defaultManager] moveItemAtURL:location toURL:documentURL error:nil];
         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Download"
                                                    message:@"Succesfully downloaded"
                                                   delegate:nil
                                          cancelButtonTitle:@"OK"
                                          otherButtonTitles:nil];
         [self.actvityIndicator stopAnimating];
         NSLog(@"wait downloading......");
         [alert show];
     }
  }];

    [downloadTask resume];    
}
2
Rahul Ranjan

Bonjour, Il est clair que vous écrivez des données NULL dans votre fichier.

Dans votre instruction de code NSData * thedata = NULL; indique que vous attribuez une valeur NULL à vos données.

Vous écrivez également des données NULL dans votre fichier.

Veuillez vérifier votre code une fois de plus.

2
Jim

Depuis que nous sommes sur IOS6 maintenant, vous n’avez plus besoin d’écrire des images sur le disque de manière nécessaire.
Depuis iOS5, vous pouvez désormais définir "autoriser le stockage externe" sur un attribut binaire coredata .

Les petites valeurs de données telles que les vignettes d’image peuvent être efficacement stockées dans un fichier base de données, mais les meilleures photos ou autres supports sont mieux gérés directement par le système de fichiers. Vous pouvez maintenant spécifier que la valeur d'un .__ géré. attribut object peut être stocké en tant qu’enregistrement externe - voir setAllowsExternalBinaryDataStorage: Lorsque cette option est activée, Core Data détermine de manière heuristique, valeur par valeur, si il devrait sauvegarder les données directement dans la base de données ou stocker un URI dans un fichier fichier séparé qu'il gère pour vous. Vous ne pouvez pas interroger sur la base du contenu d'une propriété de données binaires si vous utilisez cette option.

2
Alexander

Voici comment vous pouvez enregistrer une image de manière asynchrone dans Swift:

requestImage("http://www.asdf.com/89asdf.gif") { (image) -> Void in
    let myImage = image
}

func requestImage(url: String, success: (UIImage?) -> Void) {
    requestURL(url, success: { (data) -> Void in
        if let d = data {
            success(UIImage(data: d))
        }
    })
}

func requestURL(url: String, success: (NSData?) -> Void, error: ((NSError) -> Void)? = nil) {
    NSURLConnection.sendAsynchronousRequest(
        NSURLRequest(URL: NSURL (string: url)!),
        queue: NSOperationQueue.mainQueue(),
        completionHandler: { response, data, err in
            if let e = err {
                error?(e)
            } else {
                success(data)
            }
    })
}

Son inclus comme fonction standard dans mon repo:

https://github.com/goktugyil/EZSwiftExtensions

1
Esqarrouth

Voici un exemple de la façon dont je télécharge des bannières sur mon application. Je télécharge les images en arrière-plan et la plupart de mes applications n'utilisant pas le comptage de références, je libère des objets.

- (void)viewDidLoad {
    [super viewDidLoad];

    [NSThread detachNewThreadSelector:@selector(loadImageInBackground) toTarget:self withObject:nil];

}

- (void) loadImageInBackground {
    NSURL *url = [[NSURL alloc] initWithString:@"http://yourImagePath.png"];
    NSData *data = [[NSData alloc] initWithContentsOfURL:url];
    [url release];
    UIImage *result = [[UIImage alloc] initWithData:data];
    [data release];

    UIImageView *banner_ImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
    [self.view addSubview:banner_ImageView];
    banner_ImageView.image = result;
    [result release];
}
0
Bobby