2009-05-10 5 views
8

私はちょうどMacで開発を開始したばかりで、Cocoaは有用で思いやりのあるフレームワークだが、そのHTTP機能は私を困惑させる。Atomic、非同期のHTTPファイルPOSTとわかりやすいフィードバック?

HTTP GETメソッドを使用してWebサーバーからファイルをダウンロードするNSURLConnectionオブジェクトがあります。 NSURLConnectの非同期接続が素晴らしいです、私はたくさんのフィードバックを得て、私はクライアント側でファイルを原子的に再構築するために使用できる新しいNSDataオブジェクトとして受け取った各チャンクを取得し、重要なのは進捗レポートを提供します:[myData length ]。

アップロードは、しかし、どこにもきれいではありません。独自のスレッドに同期要求を張ったり、非同期要求を呼び出すことはできますが、どちらも有用なフィードバックを提供することはできません。データを要求したり、データの送信時に通知する代理人はいません。おそらく、これは私の利用可能なメモリよりも小さいファイルに制限されます。

私は、Cocoaを使用したHTTP POSTファイルのアップロードに簡単で洗練されたソリューションを提供しています。フィードバックはたくさんあり、ファイルを一度に読むのではなく部分的に読むことができるのですか?あるいは、低レベルのネットワーキング機能から私自身のクラスを書くべきですか?

ありがとうございます!

+0

なぜ彼らは自分のスレッドに入れさせませんか? NSOperationを使用して、/ etcを作成/管理していないことを確認できます。あなたが必要としないスレッドのトン。 POST操作からどのようなデータフィードバックが期待できますか? –

+0

これまでにアップロードしたデータ量。私は潜在的に大きなファイルを扱っているので、ユーザーにプログレスバーなどを提供する必要があります。スレッディングはそれほど問題ではありません。ファイルをロードしてフィードバックを得る能力がますます高くなっています。 不条理に速い返信のための小道具! – Dani

+0

ああ、大丈夫です!私はたぶん自分で何かを巻くだけだろう。 POST機能を備えたNSURLのまともなクラスを一度見たことは確かですが、どこかに覚えていないかもしれません。誰かがまともな回答を追加するかもしれませんが、ちょっとグーグルにしたいかもしれません。私はそれを見つけるために少し掘り起こしていたことを覚えています。 –

答えて

2

私は、NSURLConnectionの代わりにCFNetwork関数を使うことに決めました。非同期通知や特定の機能(たとえば認証など)には、柔軟性があるようです。残念ながら、それはもう少し複雑だ(例えば、実行ループが私の心を吹く)ので、私はあなたがこのルートを行く場合は、CFNetworkはリファレンスガイドを読むことをお勧めします:

http://developer.apple.com/documentation/Networking/Conceptual/CFNetwork/Introduction/Introduction.html

ここに私のPOSTルーチン、FWIWからのコードの抜粋です:

// Create our URL 
CFStringRef url = CFSTR("Submit"); 
CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, baseUrl); 

// Create the message request (POST) 
CFStringRef requestMethod = CFSTR("POST"); 
CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, myURL, kCFHTTPVersion1_1); 

// Connect the read socket to the HTTP request stream 
CFReadStreamRef myReadStream = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, myRequest, readStream); 
// TODO: why does this have to be done? 
succ &= CFReadStreamSetClient(myReadStream, 
    kCFStreamEventOpenCompleted | kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, 
    (CFReadStreamClientCallBack) &MyReadCallBack, &myClientContext); 
CFReadStreamScheduleWithRunLoop(myReadStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); 
succ &= CFReadStreamOpen(myReadStream); 

1

は残念ながら、あなたはNSURLConnectionがここに弱いことは非常に正しいです。私が推奨する最も柔軟なアプローチはCocoaAsyncSocketです。それはあなた自身のHTTPを動かすことを意味しますが、それは残念ですが、ほとんどの場合、難しくありません。 CocoaHTTPServerは、CocoaAsyncSocketの上に完全なHTTPサーバーを構築する方法を示し、問題のための多くの便利なコードを持つ場合があります。私はこれらの両方が非常に便利であることを発見しました。

調査する価値のある別のアプローチはWebKitです。目に見えないWebViewを作成し、loadRequest:POSTを実行します。 estimatedChange通知システムにアップロードする時間とダウンロードする時間だけが含まれているかどうかは分かりませんが、試してみる価値があります。

1

my toolkit repository on githubのHTTPMessageセクションで、CFHTTPMessageRefの周りの単純なObjCラッパーについて調べることができます。とりわけ、NSInputStreamオブジェクトを渡すので、プレーンCコールバック関数について考える必要がありません。

読んでいる内容に応じて、同じリポジトリのStreamingXMLParserセクションで、NSInputStreamから直接データを解析するXML(およびHTML)パーサーを調べることができます。

5

ASIHTTPRequestフレームワークを参照してください。私はアップロードのためにそれを使用していないが、それはより多くのフィードバックを持っているように見え、使用法はかなり簡単です。

2

ASIHTTPRequestはもともとこの目的のために(POST進行状況を追跡するために)設計されました。なぜなら2.x APIではNSURLConnectionではこれが不可能だったからです。CFNetworkで独自のものを作成するよりも、統合するのが確実に簡単になります(例えば、複数のリクエストの進行状況の追跡、ダウンロードの再開など)。 :)

アップロードするファイルが大きい場合は、ディスクから直接ストリーミングのオプションを確認してください。そのため、データをメモリに保持する必要はありません。

関連する問題