VS 2010 用のテンプレートです。 SkyDrive へ移動 Twitter API : POST statuses/update_with_media ❶ API 1.1 での URL は、https://api.twitter.com/1.1/statuses/update_with_media.json です。 ❷ 認証用のデータは、oauth_* のみ使って、status は使用しません ❸ 日本語投稿部分は、URLエンコードでは無く、UTF-8 で出力します ❹ UI スレッドへのアクセスは、SynchronizationContext を使用しています ❺ カスタムイベントで、投稿結果の JSON を取得します( UI スレッド ) 生データをチェックしたい場合、AN HTTPD では、トレースを出力するようにして、http://localhost/test.php を投稿先とし、test.php には OK とのみ書いておきます。 Progress が必要な場合は、wr.AllowWriteStreamBuffering = false; と wr.SendChunked = true; を実行して、ファイルを書き込むループ内で処理するか、そこから外部へのイベントを作成すれば良いと思います。 ここでは、409600 というバッファのサイズにあまり意味はありませんが、どの程度のサイズのファイルのアップロードの Progress をテストするかによって、考慮する必要が出て来ると思います。しかし、実装段階での効率の良いサイズとしては、大きすぎず、小さすぎず程度でいいと思います。 Form1.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using LBOX_Tool; using System.Net; namespace Twitter_Post_with_Media_test1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.FileName = ""; ofd.Filter = "JPEG|*.jpg;*.jpeg"; ofd.FilterIndex = 0; if (ofd.ShowDialog() != DialogResult.OK) { return; } VS2010_Twitter twitter = new VS2010_Twitter( "Consumer key", "Consumer secret", "Access token", "Access token secret" ); twitter.TwitterImageUploadResult += (object _sender, VS2010_Twitter.TwitterImageUploadArgs _e) => { this.textBox2.Text = _e.Message; }; twitter.Tweet(this.textBox1.Text, ofd.FileName); } } }
VS2010_Twitter.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Security.Cryptography; using System.Net; using System.Diagnostics; using System.IO; using System.Threading; namespace LBOX_Tool { class VS2010_Twitter { private string _consumer_key; private string _consumer_secret; private string _token; private string _secret; private SynchronizationContext sc = null; // API 1.1 における最新の URL private string _tweet_api = "https://api.twitter.com/1.1/statuses/update_with_media.json"; // イベント引き渡し用クラス private class MyParam { public WebRequest wr; public string image_path; public string strBoundary; public string text; } public VS2010_Twitter( string consumer_key, string consumer_secret, string token, string secret ) { _consumer_key = consumer_key; _consumer_secret = consumer_secret; _token = token; _secret = secret; } public void Tweet(string text, string path) { // UI スレッドに戻る為のコンテキスト sc = SynchronizationContext.Current; // ソートされるリスト SortedList<string, string> sl = new SortedList<string, string>(); sl.Add("oauth_consumer_key", _consumer_key); sl.Add("oauth_nonce", Nonce()); sl.Add("oauth_signature_method", "HMAC-SHA1"); sl.Add("oauth_timestamp", TimeStamp()); sl.Add("oauth_token", _token); sl.Add("oauth_version", "1.0"); // 画像投稿では、以上で認証用のデータを作成する( status は使用できない ) // http ヘッダ用シグネチャ作成 string work = ""; foreach (KeyValuePair<string, string> kvp in sl) { if (work != "") { work += "&"; } work += kvp.Key + "=" + kvp.Value; } string work2 = ""; // メソッド work2 += "POST" + "&"; // API URL work2 += Uri.EscapeDataString(_tweet_api) + "&"; // Oauth + データ work2 += Uri.EscapeDataString(work); // OAuth tool チェック用 Debug.WriteLine(work2); string oauth_signature = Signature(work2); // ヘッダ情報を作成 work = ""; foreach (KeyValuePair<string, string> kvp in sl) { // oauth_* のみを使用する if (work != "") { if (kvp.Key.Substring(0, 6) == "oauth_") { work += ", "; } } if (kvp.Key.Substring(0, 6) == "oauth_") { work += kvp.Key + "=" + Dd(kvp.Value); } } // シグネチャを追加( ヘッダーはソートの必要は無い ) work += ", oauth_signature=" + Dd(Uri.EscapeDataString(oauth_signature)); // OAuth tool チェック用 Debug.WriteLine(work); // 投稿準備(1) string strBoundary = DateTime.Now.Ticks.ToString("x"); HttpWebRequest wr = (HttpWebRequest)HttpWebRequest.Create(_tweet_api); // 生データをチェックしたい場合 // HttpWebRequest wr = (HttpWebRequest)HttpWebRequest.Create("http://localhost/test.php"); // Progress が必要な場合 //wr.AllowWriteStreamBuffering = false; //wr.SendChunked = true; // HttpWebRequest の基本部分の設定 wr.Method = "POST"; wr.ContentType = "multipart/form-data; boundary=---" + strBoundary; wr.Headers["Authorization"] = "OAuth " + work; // ストリームへの書き込みイベント AsyncCallback writeCallBack = new AsyncCallback(WriteCallBack); MyParam myParam = new MyParam() { wr = wr, image_path = path, strBoundary = strBoundary, text = text }; // 呼び出し IAsyncResult iar1 = wr.BeginGetRequestStream(writeCallBack, myParam); } // 書き込み public void WriteCallBack(IAsyncResult ar) { HttpWebRequest req = (HttpWebRequest)(ar.AsyncState as MyParam).wr; string path = (ar.AsyncState as MyParam).image_path; string strBoundary = (ar.AsyncState as MyParam).strBoundary; string text = (ar.AsyncState as MyParam).text; // 書き込み用のストリーム Stream sw = req.EndGetRequestStream(ar); // ▼ 以下、Twitter のドキュメントサンプル //--cce6735153bf14e47e999e68bb183e70a1fa7fc89722fc1efdf03a917340 //Content-Disposition: form-data; name="status" // //Hello 2012-09-07 15:51:41.375247 -0700 PDT! //--cce6735153bf14e47e999e68bb183e70a1fa7fc89722fc1efdf03a917340 //Content-Type: application/octet-stream //Content-Disposition: form-data; name="media[]"; filename="media.png" //... //--cce6735153bf14e47e999e68bb183e70a1fa7fc89722fc1efdf03a917340-- // 書き込み処理 Encoding encoding = Encoding.ASCII; // セクション(1) / 日本語投稿本文 Byte[] content = encoding.GetBytes("-----" + strBoundary + "\r\n"); sw.Write(content, 0, content.Length); content = encoding.GetBytes("Content-Disposition: form-data; name=\"status\"\r\n\r\n"); sw.Write(content, 0, content.Length); content = Encoding.GetEncoding("UTF-8").GetBytes(text + "\r\n"); sw.Write(content, 0, content.Length); // セクション(2) / 生バイナリ画像部分 content = encoding.GetBytes("-----" + strBoundary + "\r\n"); sw.Write(content, 0, content.Length); content = encoding.GetBytes("Content-Type: application/octet-stream\r\n"); sw.Write(content, 0, content.Length); content = encoding.GetBytes("Content-Disposition: form-data; name=\"media[]\"; filename=\"media.jpg\"\r\n\r\n"); sw.Write(content, 0, content.Length); // ファイルのバイナリデータ( バッファサイズの大きさにあまり意味はありません ) FileStream fs = new FileStream(path, FileMode.Open); int buffer_len = 409600; long length = 0; int read_size = 0; byte[] file_data = new byte[buffer_len]; while ((read_size = fs.Read(file_data, 0, buffer_len)) > 0) { length += read_size; Debug.WriteLine("writing...." + length); sw.Write(file_data, 0, read_size); if (read_size < buffer_len) { break; } } fs.Close(); fs.Dispose(); // multipart の終了 content = encoding.GetBytes("\r\n-----" + strBoundary + "--\r\n"); sw.Write(content, 0, content.Length); sw.Close(); sw.Dispose(); // 最終的なレスポンスの取得 AsyncCallback readCallBack = new AsyncCallback(this.ReadCallBack); IAsyncResult iar2 = req.BeginGetResponse(readCallBack, req); } // 読み込み public void ReadCallBack(IAsyncResult ar) { string result = ""; HttpWebRequest req = (HttpWebRequest)ar.AsyncState; HttpWebResponse response = null; // ここで時々接続が切られたりします try { response = (HttpWebResponse)req.EndGetResponse(ar); Encoding enc = System.Text.Encoding.GetEncoding("UTF-8"); StreamReader sr = new StreamReader(response.GetResponseStream(), enc); result = sr.ReadToEnd(); Debug.WriteLine(result); sr.Close(); sr.Dispose(); } catch (Exception ex) { result = ex.Message; Debug.WriteLine(result); } // 内部のイベントの呼び出し( 最終的なイベントを UI スレッドで実行させる ) sc.Post((object state) => { OnTwitterImageUploadResult(new TwitterImageUploadArgs(result)); }, null); } // *************************************************** // カスタムイベント用引数 // *************************************************** public class TwitterImageUploadArgs : EventArgs { // 引数の保存エリア private string message; // コンストラクタ public TwitterImageUploadArgs(string s) { message = s; } // 引数取り出し用のプロパティ public string Message { get { return message; } } } // *************************************************** // カスタムイベントハンドラの定義 ( EventHandler<T> ) // *************************************************** public event EventHandler<TwitterImageUploadArgs> TwitterImageUploadResult; // *************************************************** // 外部へイベントを発行する為の内部メソッドの定義( virtual ) // *************************************************** protected virtual void OnTwitterImageUploadResult(TwitterImageUploadArgs e) { EventHandler<TwitterImageUploadArgs> handler = TwitterImageUploadResult; // イベントが外部で実装されている場合、そのイベントを呼び出す if (handler != null) { handler(this, e); } } // ダブルクォートで挟む private string Dd(string base_string) { return "\"" + base_string + "\""; } private string Nonce() { Random rand = new Random(); int nonce = rand.Next(1000000000); return nonce.ToString(); } // タイムスタンプ private string TimeStamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } // シグネチャ private string Signature(string target) { string work = _consumer_secret + "&" + _secret; byte[] bin = Encoding.UTF8.GetBytes(target); HMACSHA1 hmacsha1 = new HMACSHA1(); hmacsha1.Key = Encoding.UTF8.GetBytes(work); byte[] hash = hmacsha1.ComputeHash(bin); return Convert.ToBase64String(hash); } } }
関連する記事 ❶ Twitter API 1.1 : POST statuses/update_with_media / 画像付き投稿 -- の注意事項 ❷ Windows Phone から Facebook に画像アップロード
|
【VS(C#)の最新記事】
- Replit : cs-list
- C# : Excel の新しいブックのデフォルトのシートのセルに直接値をセットして、オートフィルを Range オブジェクトから実行する
- C#( Form ) : ウインドウ枠の無い吹き出しの作成
- C# のタプル( Visual Studio 2017 でテスト )
- C# : インターネット上の JSON ファイルのフォーマットを クラスとして定義して1行でオブジェクト化して使用する
- C# の文法的文字列処理
- C# : System.Data.Odbc によるデータベースのテーブルからのデータ取得処理( サンプルの SQL は MySQL 用です )
- C# : Excel を データベースとして DataGridView に読み込む
- C# : dynamic 型 による Excel へのアクセス
- C# : フォームを表示せずに、通知領域にアイコンを表示させる常駐プログラム
- Microsoft Access に対してSQLを入力してその結果を DataGridView に表示する最も簡単なコード
- C# : System.Data.Odbc データ取得(SELECT)処理( MySQL ) : ※ using 無し( Dispose 実行 )
- C# : SQL 文を外部テキストにして、String.Format でデータ部分を置き換えて利用する
- C# コンソールアプリを AN HTTPD で実行
- C# : SQLServer( SQLExpress ) の SMO を使用してテーブルの CREATE TABLE 文 を取得する
- C# : DataGridView に TKMP.DLL の IMAP(POP3) で受信したメールを非同期に表示する( 添付ファイルも取得 )
- C# : TKMP.DLLを使った、メール送信テンプレート
- C# と VB.net : TKMP.DLL を使って IMAP でメール本文の一覧を取得する( コンソール )
- C# でDataTable と DataSource を使用して、DataGridView にデータを表示するテンプレート( 行をダブルクリックしてダイアログを表示して行データを処理 )
- (C#) / VS2010 または VS2012 : TKMP.DLL(3.1.2 または 3.1.8)を使った、『さくらインターネット』用メール送信テンプレート