Supponiamo che abbiate creato un’applicazione per ritoccare le immagini scattate. Inviarle per email non vi soddisfa e vorreste trovare una via più veloce per trasferirle sul vostro computer collegato in rete locale. Un modo semplice per condividere files tra iPhone e computer via WiFi è quello di creare un web server lato iPhone e accedere ai contenuti da un browser inserendo l’indirizzo locale del vostro telefono. In questo tutorial impareremo ad implementare un framework open source all’interno delle nostre applicazioni.
Esistono diversi progetti gratuiti ma il più promettente è sicuramente CocoaHttpServer disponibile su Google Code. Si tratta di un insieme di classi che si preoccupano di impostare un server HTTP al quale potranno collegarsi altri computer sulla stessa rete locale inserendo l’indirizzo IP del nostro iPhone. Al momento il progetto supporta il protocollo HTTP 1.1 ma non il WebDAV. Questo vuol dire che sarà possibile collegarsi ad iPhone attraverso Safari (o altri browser) ma non direttamente dal Finder (tipo AirSharing o Files).
Scarichiamo dunque il file iPhoneHTTPServer3.zip che contiene tutte le librerie necessarie, scompattiamolo in una cartella e lanciamo il progetto iPhoneHTTPServer.xcodeproj. A questo punto, a seconda dell’OS con cui state sviluppando potrebbe essere necessario aggiornare il target. Fate così: nella barra laterale di XCode cliccate su Targets, selezionate iPhoneHTTPServer con il tasto destro del mouse e scegliete Get Info. A questo punto nel tab Build impostate il vostro Base SDK. Nel mio caso è iPhone Device 3.0. Se volete svilupparlo su iPhone invece del Simulatore ricordatevi anche di impostare il Code Signing e di associarvi un profilo valido. Chiudete la finestra e impostate con il menu popup in alto a sinistra della toolbar di XCode l’SDK prescelto.

A questo punto compilate e lanciate l’applicazione (tasto mela+R). Se necessario attivate il server cliccando sullo switch in centro allo schermo. Se tutto funziona iPhone vi restituirà il vostro indirizzo IP seguito dalla prima porta libera individuata. Potrebbe volerci qualche secondo. Nel mio caso è http://192.168.0.2:50334. Se ora inserite questo indirizzo in Safari aprirete una pagina dalla quale è possibile uploadare files all’iPhone. A noi interessa di più il processo inverso.
L’obbiettivo del piccolo progetto che svilupperemo è quello di consentire ad un browser esterno di scaricare una o più immagini presentate dall’applicazione. Chiaramente potete usare tutte le immagini che volete. Se non ne avete a portata di mano nessuna, potete scaricare questa: (tasto destro sull’immagine e poi Salva con nome…)

Rinominatela photo.jpg e trascinatela sulla cartella Resource nella barra laterale di XCode. Lasciate il tasto del mouse. Apparirà una finestra che vi chiederà se volete aggiungerla al progetto. Ricordatevi di selezionare l’opzione per copiarla nella cartella del progetto.

A questo punto possiamo iniziare a scrivere qualche riga di codice. Tutti i files e le immagini referenziate dal nostro http server devono trovarsi nella cartella documenti della nostra applicazione. La prima cosa che dobbiamo fare quindi è copiare l’immagine photo.jpg in questa cartella. Apriamo quindi il file iPhoneHTTPServerAppDelegate.m e inseriamo all’inizio del primo metodo le seguenti righe:
– (void)applicationDidFinishLaunching:(UIApplication *)application
{
NSError *error;
NSString *docDirectory = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] retain];
NSString *httpImagePath=[docDirectory stringByAppendingPathComponent:@”photo.jpg”];
NSLog(@”%@”,httpImagePath);
if( ![[NSFileManager defaultManager] fileExistsAtPath:httpImagePath] )
{
NSString *httpImagePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@”photo.jpg”];
NSLog(@”%@”,httpImagePathFromApp);
[[NSFileManager defaultManager] copyItemAtPath:httpImagePathFromApp toPath:httpImagePath error:&error];
}
…
La variabile error contiene l’eventuale errore di un’operazione su files. La seconda riga trova il percorso della cartella documenti, mentre la terza riga crea il percorso all’immagine (attenzione: è il percorso dell’immagine che copieremo non il percorso dell’immagine presente nel bundle dell’applicazione). Ci sono un paio di NSLog per vedere i risultati nella console durante il debug. Ora l’if si preoccupa di non copiare l’immagine se è già stata copiata in precedenza. Diversamente ottiene il percorso dell’immagine presente nel bundle dell’applicazione e la copia nella cartella documenti. Adesso dobbiamo preoccuparci di creare la pagina HTML che la nostra applicazione presenterà ad ogni browser che si connette.
Prima di mettere mano al codice è però opportuno capire che cosa fanno i vari files. Le cartelle HTTP, TCP e Categories svolgono il lavoro più complicato: inizializzano il server, gestiscono le connessioni asincrone, rispondono alle richieste esterne il tutto in perfetta aderenza ai protocollo TCP e HTTP.
Noi focalizzeremo l’attenzione su MyHTTPConnection.m. Questa classe contiene il metodo
– (NSString *)createBrowseableIndex:(NSString *)path
che si preoccupa di presentare la pagina di risposta alle richieste che arrivano dall’esterno. Si tratta sostanzialmente di creare una pagina HTML sotto forma di stringhe in puro stile Objective-C.
– (NSString *)createBrowseableIndex:(NSString *)path
{
NSArray *array = [[NSFileManager defaultManager] directoryContentsAtPath:path];
NSMutableString *outdata = [NSMutableString new];
[outdata appendString:@”<html><head>”];
[outdata appendFormat:@”<title>Il mio web server</title>”];
[outdata appendString:@”</head><body>”];
[outdata appendString:@”<p>”];
[outdata appendFormat:@”<img src=photo.jpg>”];
[outdata appendString:@”</p>”];
[outdata appendString:@”</body></html>”];
//NSLog(@”outData: %@”, outdata);
return [outdata autorelease];
}
Il codice è molto semplice: crea una pagina web con un solo elemento: un’immagine. Come potete vedere il nome è photo.jpg e il programma andrà a pescarla nella cartella documenti. Se a questo punto avete fatto tutto correttamente, lanciando l’applicazione e aprendo da Safari la pagina web relativa vi troverete davanti a questa schermata:

In un prossimo tutorial vedremo come cambiare gli httpHeaders per impostare lo scaricamento automatico di files e immagini.












11 Responses to “T#014 – Un web server per scaricare files e immagini”
2 Dicembre 2009
walterDavvero ottimo 🙂
16 Gennaio 2010
Cenzeccellente, forse la soluzione migliore per comunicare tra iphone e desktop.
C’è modo di caricare / scaricare folders interi invece di singoli file?
16 Gennaio 2010
theolternativeChe io sappia no. Ai tempi avevo cercato ma non avevo trovato nulla.
16 Gennaio 2010
CenzSe io creo un subfolder nel folder documents e ci salvo una serie di files (immagini), quando vado sul server via Bonjour da safari vedo i subfolders, cliccandoci sopra me li apre, ma i files non me li elenca. So che ci sono perché dall’applicazione li ritrova, ma il webserver non li mostra. C’è modo di elencarli? Non li voglio tenere nel folder Documents perchè sono molti file immagine che devono stare separati dagli altri documenti. In alternativa potrei compattarli tutti in un file zippato e presentare solo il file zippato. Ma come posso zippare un intero subfolder da iPhone?
16 Gennaio 2010
Cenzoppure come posso fare un download automatico di tutti i files? (rischiano di essere un centinaio). ho visto che ti sei ripromesso di farne un prossimo tutorial, ma non è possibile averne un’anticipazione?
grazie e ancora complimenti per l’ottimo e utilissimo sito.
17 Gennaio 2010
theolternativePer fare il download di tanti files l’unico modo è zipparli. Cerca su Google Zip Library iPhone
17 Gennaio 2010
theolternativePer elencare il contenuto dei subfolder bisogna costruire l’output così come avviene per index.html.
Guarda in fondo al metodo:
– (NSObject *)httpResponseForMethod:(NSString *)method URI:(NSString *)path
in MyHTTPConnection.m
17 Novembre 2010
alessioQuComplimenti, post molto interessante!!
Però ho un problema 🙁 .Quando faccio l’upload delle immagini tramite il metodo POST, se 2 files hanno lo stesso nome l’applicazione va in crash. Qualcuno di voi sa come posso fare per ovviare a questo problema?
Grazie in anticipo!
26 Novembre 2010
alessioQuHo risolto da solo!!!! GRAZIE
6 Dicembre 2010
devAPP – Tutorial Set #3 - iPhone Italia – Il blog italiano sull'Apple iPhone 4, iPhone 3GS e 3G[…] (Vai al tutorial completo) […]
7 Settembre 2011
iVinceQuale metodo bisogna invocare per fare partire il server quando vogliamo noi?