Télécharger des fichiers

TchouboudouTchouboudou Membre
03:07 modifié dans API AppKit #1
Bonsoir tout le monde...

Le téléchargement de fichier m'interresse, et j'ai cherché sur ce forum. J'ai trouvé quelques sujet, mais je n'ai pas comprs grand chose. Pouvez-vous m'expliquez comment faire (juste un téléchargement simple).

Merci d'avance,
Tchouboudou

Réponses

  • BruBru Membre
    03:07 modifié #2
    Il y a des milliards de solutions en cocoa pour télécharger une ressource...
    Mais comme tu ne précises pas grand chose (qu'est ce qui est téléchargé, quel protocole, quelle utilisation), je te donnerai la méthode générique le plus simple :

    <br />{<br />    NSURL *url;<br />    NSData *data;<br /><br />    // création de l&#39;url qui pointe vers la ressource à  télécharger<br />    url=[NSURL URLWithString:@&quot;http://www.objective-cocoa.org/forum/Themes/classic/images/logo.png&quot;];<br /><br />    // téléchargement de la ressource pointée par l&#39;url (le résultat est mis en NSData)<br />    data=[url resourceDataUsingCache:NO];<br /><br />    // écriture du NSData dans un fichier sur le disque dur à  la racine<br />    [data writeToFile:@&quot;/logo.png&quot; atomically:NO];<br />}<br />
    


    Dans l'exemple, la ressource est un fichier .png qui contient le logo Objective-cocoa.

    .
  • TchouboudouTchouboudou Membre
    03:07 modifié #3
    Ce que j'aimerais, c'est faire un téléchargement du style de Safari (mais juste un téléchargemlent à  la fois me suffit).

    Merci de ta réponse.
  • 03:07 modifié #4
    Un téléchargement à  la fois ? Tu simplifies ta vie :D Je te fais un exemple ce soir ;-)
  • TchouboudouTchouboudou Membre
    03:07 modifié #5
    Pour l'instant, après, j'verrais les threads, tout ça tout ça :D
  • BruBru Membre
    septembre 2006 modifié #6
    Voici un squelette de ce que tu veux faire :

    <br />@interface Telechargeur : NSObject<br />{<br />    NSMutableData *rData;<br />    long long taille;<br />}<br />@end<br /><br />@implementation Telechargeur<br /><br />- (void)telecharger<br />{<br />    NSURL *url;<br />    NSURLRequest *urlReq;<br />    NSURLConnection *urlCnx;<br /><br />    // création de l&#39;url qui pointe vers la ressource à  télécharger<br />    url=[NSURL URLWithString:@&quot;http://www.objective-cocoa.org/forum/Themes/classic/images/logo.png&quot;];<br /><br />    // création des objets nécessaires au téléchargement (requête et connexion)<br />    urlReq=[NSURLRequest requestWithURL:url];<br />    urlCnx=[NSURLConnection connectionWithRequest:urlReq delegate:self];<br />}<br /><br />// méthode appelée au commencement du téléchargement<br />- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response<br />{<br />&nbsp; &nbsp; // récupération de la taille de la ressource à  télécharger<br />&nbsp; &nbsp; taille=[response expectedContentLength];<br /><br />&nbsp; &nbsp; // création du NSData qui va recevoir le téléchargement<br />&nbsp; &nbsp; rData=[[NSMutableData alloc] init];<br />}<br /><br />// méthode appelée à  chaque réception d&#39;un morceau de ressource<br />- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data<br />{<br />    int pourcent;<br /><br />    // récupération du morceau de ressource téléchargée et ajout dans rData<br />    [rData appendData:data];<br /><br />    // calcul du pourcentage téléchargé et affichage<br />    pourcent=(float)[rData length]/(float)taille*100.0;<br />    NSLog(@&quot;%i%% téléchargés&quot;, pourcent);<br />}<br /><br />// méthode appelée quand le téléchargement est terminé<br />-(void)connectionDidFinishLoading:(NSURLConnection *)connection<br />{<br />    // écriture d rData sur le disque<br />    [rData writeToFile:@&quot;/logo.png&quot; atomically:NO];<br />}<br /><br />@end<br />
    


    C'est le squelète d'une classe nommée "Telechargeur".
    La méthode telecharger entame la session de téléchargement (création d'une url, puis d'une requête de lecture de l'url, et enfin établissement d'une connexion).
    La connexion est asynchrone (les données sont reçues en tâche de fond).
    Des méthodes delegate sont appelées pour suivre le téléchargement.
    J'en utilise 3 : la première pour débuter la session de téléchargement (création du NSData, récupération de la taille de la ressource à  télécharger), la seconde pour accumuler les données reçues dans le NSData et pour afficher le pourcentage de progression, et la dernière pour enregistrer toutes les données reçues sur le disque.

    La parole est à  Tchouboudou.

    .
  • 03:07 modifié #7
    Oui comme l'a dit bru, lorsque tu init un NSURLDownload, c'est comme si tu créais (je sais pas si j'ai fait une faute ou non, le correcteur me dis que non en tout cas :p) un nouveau thread qui se chargera de télécharger (c'est pour ça que j'aime bien NSURLDownload :p)
    Là  je pense que bru t'as donné suffisamment d'informations donc je ne vais pas te faire d'exemple même si ça m'aurait amusé.
    Après si tu veux savoir comment incrémenter un NSProgressIndicator en fonction du téléchargement, savoir le débit, etc..., n'hésites pas
  • BruBru Membre
    03:07 modifié #8
    dans 1158869701:

    Là  je pense que bru t'as donné suffisamment d'informations donc je ne vais pas te faire d'exemple même si ça m'aurait amusé.


    Je vois, je vois... L'élève a dépassé ses (anciens) (maà®tres) !

    [size=7pt]
    PS : je préfère utiliser NSURLConnection plutôt que NSURLDownload... D'après la doc Apple, NSURLConnection semble plus "évolué", ou de plus haut niveau (prise en compte du cache et des redirections)...
    [/size]

    .
  • TchouboudouTchouboudou Membre
    03:07 modifié #9
    Très interressant, merci...

    J'ai une question, un simple tableau contenant des instances de la classe Telechargeur (pour reprendre l'exemple de Bru) ne suffirait-il pas à  faire plusieurs téléchargement ?
  • BruBru Membre
    03:07 modifié #10
    dans 1158939451:

    J'ai une question, un simple tableau contenant des instances de la classe Telechargeur (pour reprendre l'exemple de Bru) ne suffirait-il pas à  faire plusieurs téléchargement ?


    Je pense que oui... Mais c'est à  tester.
    Par contre, cela demandera une gestion sérieuse des états d'avancement des téléchargements (via un NSProgressIndicator par exemple).

    Le jeune padawan Louka (Eaglelouk) de donnera toutes les pistes possibles.

    Au fait, les téléchargements, c'est pour quoi ?
    Parce que si tu nous refais un énième gestionnaire FTP, on a ce qu'il faut (d'autant plus que Le Chat Noir nous en concocte un de derrière les fagots).

    .
  • TchouboudouTchouboudou Membre
    septembre 2006 modifié #11
    Ho non, c'est pour m'amuser :D

    Aussi, pourquoi un long long comme type de variable ?
  • 03:07 modifié #12
    Personnellement, pour iFreete j'ai une simple NSMutableArray qui contient des NSMutableDictionary qui elles-même contiennent par exemple le titre du fichier, le download (NSURLDownload), le chemin de destination, etc...
    Pour ce qui est de faire un NSProgressIndicator à  chaque ligne d'une TableView, c'est un peu plus complexe, mais la solution la plus simple est de créer un nouveau fichier interface (Nib) et d'y ajouter une NSView, et là  tu présentes comme tu veux sachant que ça sera la ligne de référence de ta tableView.

    Mais initialisé une nouvelle classe pour chaque téléchargement, ça peut être plus simple, car moi à  chaque vois que je reçois - (void)download:(NSURLDownload *)download didReceiveDataOfLength:(unsigned)length{}, je met un petit while afin de récupérer le NSMutableDictionary qui correspond au NSURLDownload (et ça surcharge un peu)
  • TchouboudouTchouboudou Membre
    septembre 2006 modifié #13
    J'ai ce code, qui devrait normalement me permettre de faire une barre de progression. Malheuresement, ça ne marche pas.

    - (IBAction)lancer:(id)sender<br />{<br />&nbsp; &nbsp; NSURL *url;<br />&nbsp; &nbsp; NSURLRequest *urlReq;<br />&nbsp; &nbsp; NSURLConnection *urlCnx;<br /><br />&nbsp; &nbsp; // création de l&#39;url qui pointe vers la ressource à  télécharger<br />&nbsp; &nbsp; url=[NSURL URLWithString:@&quot;http://www.objective-cocoa.org/forum/Themes/classic/images/logo.png&quot;];<br /><br />&nbsp; &nbsp; // création des objets nécessaires au téléchargement (requête et connexion)<br />&nbsp; &nbsp; urlReq=[NSURLRequest requestWithURL:url];<br />&nbsp; &nbsp; urlCnx=[NSURLConnection connectionWithRequest:urlReq delegate:self];<br />	<br />	timer = [[NSTimer scheduledTimerWithTimeInterval:0.2<br />					&nbsp; target:self<br />					&nbsp; selector:@selector(checkThem:)<br />					&nbsp; userInfo:nil<br />					&nbsp; repeats:YES] retain];<br />}<br /><br />- (void)checkThem:(NSTimer *)aTimer<br />{<br />	if (taille &lt; tailleMax)<br />	{<br />		[barre setDoubleValue:(100.0 * taille) / [rData length]];<br />	}<br />}
    


    EDIT : En fait, c'est bon, j'ai juste inverser des variables.
  • 03:07 modifié #14
    Pas besoin de timer, tu implémente la progression du timer dans
    # code de Bru :
    <br />- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data<br />{<br />&nbsp; &nbsp; int pourcent;<br /><br />&nbsp; &nbsp; // récupération du morceau de ressource téléchargée et ajout dans rData<br />&nbsp; &nbsp; [rData appendData:data];<br /><br />&nbsp; &nbsp; // calcul du pourcentage téléchargé et affichage<br />&nbsp; &nbsp; pourcent=(float)[rData length]/(float)taille*100.0;<br />&nbsp; &nbsp; [progressIndicator setDoubleValue:pourcent]; // Ne pas oublier de régler min = 0.0 et max = 100.0<br />}<br />
    
  • TchouboudouTchouboudou Membre
    03:07 modifié #15
    Je repose ma chtite question, à  quoi sert le long long ? C'est quoi la différence avec un simple long ?
  • BruBru Membre
    03:07 modifié #16
    dans 1159000004:

    Je repose ma chtite question, à  quoi sert le long long ? C'est quoi la différence avec un simple long ?


    Le long long, abréviation de signed long long int, est un entier de 64 bits (8 octets).
    Le prototype de la méthode expectedContentLength de NSURLResponse renvoie un long long, c'est dans la la doc.
    Cela autorise (en théorie) le téléchargement de ressources de taille supérieure à  4 go.

    .
  • TchouboudouTchouboudou Membre
    03:07 modifié #17
    Oki merci beaucoup...
  • AliGatorAliGator Membre, Modérateur
    03:07 modifié #18
    Vaste question sur laquelle il y avait eu un débat dans ces forums.

    En résumé :
    - le "char" est sur un unique octet (8 bits)
    - le "short" est sur 2 octets (16 bits)
    - le "long" est sur 4 octets (32 bits)
    - le "long long" est sur 8 octets (64 bits)

    Et le int (sans autre précisions)... ben c'était justement tout l'objet du débat, à  savoir si ça correspondait à  un long sur toutes les machines, ou selon si on était sur une machine 32 bits ou 64 bits.
    short, long et long long sous-entendent le "int" derrière (c'est à  dire que tu peux indifférament écrire "short" ou "short int", de même pour "long" ou "long int", etc. Mais quand tu ne précises rien de plus que "int", en général ça dépend du compilateur, moi je dirais que le "int" est souvent équivalent à  un "long int" c'est à  dire sur 32 bits, mais certains disent que "int" prend la taille du bus de données, soit 32 bits sur les machines 32 bits, 64 bits sur les machines 64 bits... Pour moi c'est aux bonnes graces du compilo.

    Voilà , donc pour en revenir aux "long long", un "long long" permet de stocker des nombres 2x plus grands qu'un long normal, c'est tout :P

    [EDIT]Zut j'avais pas vu qu'il y avait une 2e page :P Avec déjà  la réponse de Bru :)
  • 03:07 modifié #19
    dans 1159010185:

    Voilà , donc pour en revenir aux "long long", un "long long" permet de stocker des nombres 2x plus grands qu'un long normal, c'est tout :P


    Je dirais plutôt 4294967296 fois plus grands, mais bon, les goûts et les couleurs, ça ne discute pas.
  • AliGatorAliGator Membre, Modérateur
    septembre 2006 modifié #20
    C'était pour voir si tu suivais :P

    Au temps pour moi ;)
    Oui, bien sûr, la taille en octets es multipliée par 2, donc le nombre le plus grand stockable dedans est élevé au carré, de 2^32 possibilités on passe à  2^64.

    Mais bon si tu veux jouer à  ça, c'est pas forcément 4294967296 (2^32) fois plus grand, mais (2^32+1) fois (4294967297x), puisqu'on passe de 2^32-1 à  2^64-1 = (2^32-1)*(2^32+1)...  ;)

    Sans parler de quand ils sont unsigned et donc que le bit de poids fort sert pour indiquer le signe, et que le nombre de possibilités est donc divisé par 2... :P

    (Si c'est pas ça qu'on appelle du pinaillage...  :P)
  • 03:07 modifié #21
    Ali, "Au temps pour moi" ça existe pas  :o C'est pas plutôt "Autant pour moi"  ;D ;D ;D
  • TchouboudouTchouboudou Membre
    03:07 modifié #22
    dans 1159012883:

    C'était pour voir si tu suivais :P

    Au temps pour moi ;)
    Oui, bien sûr, la taille en octets es multipliée par 2, donc le nombre le plus grand stockable dedans est élevé au carré, de 2^32 possibilités on passe à  2^64.

    Mais bon si tu veux jouer à  ça, c'est pas forcément 4294967296 (2^32) fois plus grand, mais (2^32+1) fois (4294967297x), puisqu'on passe de 2^32-1 à  2^64-1 = (2^32-1)*(2^32+1)...  ;)

    Sans parler de quand ils sont unsigned et donc que le bit de poids fort sert pour indiquer le signe, et que le nombre de possibilités est donc divisé par 2... :P

    (Si c'est pas ça qu'on appelle du pinaillage...  :P)


    J'en demandais pas tant  :) :)
  • BruBru Membre
    03:07 modifié #23
    dans 1159019916:

    Ali, "Au temps pour moi" ça existe pas  :o C'est pas plutôt "Autant pour moi"  ;D ;D ;D


    Aà¯e... Eagle, tu es en terrain miné.
    Je laisse Ali t'achever !

    .
  • TchouboudouTchouboudou Membre
    03:07 modifié #24
    dans 1159021409:

    dans 1159019916:

    Ali, "Au temps pour moi" ça existe pas  :o C'est pas plutôt "Autant pour moi"  ;D ;D ;D


    Aà¯e... Eagle, tu es en terrain miné.
    Je laisse Ali t'achever !

    .


    Pourquoi je sens que ça va se finir par un lien vers le sitede l'académie fraçaise :) ?
  • 03:07 modifié #25

    On peut aussi signaler le cas fort connu de au temps pour moi [1]. Initialement une formule militaire, il a été transformé en autant pour moi, que certains revendiquent comme une ellipse de c?est autant pour moi. Ainsi, un terme ayant son origine dans une étymologie populaire finit-il par acquérir son indépendance (ici en devenant une ellipse).]

    Ali espèce de militaire

    Sinon on peut finir en match nul la dessus :

    La véritable et seule authentique forme réelle avérée -- certifiée Dauzat pur sucre et non allégée -- est : " aux tempes pour moi "
  • AliGatorAliGator Membre, Modérateur
    03:07 modifié #26
    C'est bien il s'achève limite tout seul :D

    Bah honnêtement j'en sais trop rien, on en avait longuement causé sur macfr, il en était ressorti qu'apparament "au temps pour moi" était l'expression d'origine, née dans un contexte militaire, et que ça a dévié en "autant pour moi" qui finalement est passé dans le langage courant...

    Mais je suis pas prof de français, alors bon :P
    On relance le débat ?  :)
  • laurrislaurris Membre
    03:07 modifié #27
    Vous n'y êtes pas du tout. Cette expression vient de la réponse qu'aurait fait Lyndon Jonhson au général de Gaulle quand ce dernier lui annonça son retrait de l'alliance atlantique. "OTAN pour moi" aurait'il dit. Ca reste à  confirmer !
  • 03:07 modifié #28
    dans 1159035228:

    Vous n'y êtes pas du tout. Cette expression vient de la réponse qu'aurait fait Lyndon Jonhson au général de Gaulle quand ce dernier lui annonça son retrait de l'alliance atlantique. "OTAN pour moi" aurait'il dit. Ca reste à  confirmer !


    Excellent  :P

    Bon je demanderai à  ma prof de français. Ho remarque, j'ai ma journée d'appel de préparation à  la défense Lundi, autant demander là  bas, mais ils vont sûrement me dire "Au temps pour moi".  <3 <br />
    Bon ne dérivons pas trop non plus (j'avous je l'ai cherché :p)
Connectez-vous ou Inscrivez-vous pour répondre.