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)を使った、『さくらインターネット』用メール送信テンプレート







