はてなフォトライフに画像をアップロードするプログラムをC#で実装してみた
自分のコスプレ写真を(ry
前回に引き続き、今回ははてなフォトライフに画像をアップロードするC#ライブラリをまとめます。
http://developer.hatena.ne.jp/ja/documents/fotolife/apis/atom
概要
はてなのユーザIDとパスワードを指定すると、はてなフォトライフに画像をアップロードできるライブラリ。
※前回のWSSE認証のヘッダを生成するライブラリが必要です。http://cpp.kanaharu.com/entry/2013/01/06/132031
HatenaPhotoLifeUploader.cs
using System; using System.Text; using System.IO; using System.Net; namespace Harunakasoft.Library { public class HatenaPhotoLifeUploader { /// <summary> /// コンストラクタ /// </summary> /// <param name="userName">はてなユーザ名</param> /// <param name="password">はてなパスワード</param> public HatenaPhotoLifeUploader(string userName, string password) { this.hatenaAccount = new HatenaAccount(userName, password); } /// <summary> /// コンストラクタ /// </summary> /// <param name="hatenaAccount">はてなアカウント</param> public HatenaPhotoLifeUploader(HatenaAccount hatenaAccount) { this.hatenaAccount = hatenaAccount; } /// <summary> /// 画像をアップロードする /// </summary> /// <param name="path">画像パス</param> /// <param name="title">画像タイトル</param> /// <param name="folder">画像フォルダ</param> public void Upload(string path, string title, string folder = "") { byte[] data = GetImageBinaryData(path); Upload(data, title, folder); } /// <summary> /// 画像をアップロードする /// </summary> /// <param name="data">画像バイナリデータ</param> /// <param name="title">画像タイトル</param> /// <param name="folder">画像フォルダ</param> public void Upload(byte[] data, string title, string folder = "") { // アップロード用XML作成 string uploadXML = MakeUpdateXML(data, title, folder); byte[] uploadBinary = Encoding.UTF8.GetBytes(uploadXML); // POST実行 logger.Info("画像アップロード[POST]開始"); logger.Info(" title =" + title); logger.Info(" folder =" + folder); HttpWebRequest request; Stream stream; try { request = (HttpWebRequest)WebRequest.Create("http://f.hatena.ne.jp/atom/post"); request.Headers.Add("X-WSSE", hatenaAccount.WSSEHeader); request.Method = "POST"; stream = request.GetRequestStream(); stream.Write(uploadBinary, 0, uploadBinary.Length); stream.Close(); } catch (Exception e) { logger.Error("画像アップロード[POST]失敗 message=" + e.ToString()); throw e; } logger.Info("画像アップロード[POST]終了"); // レスポンス待ち logger.Info("画像レスポンス待ち開始"); try { WebResponse response = request.GetResponse(); Stream resStream = response.GetResponseStream(); StreamReader reader = new StreamReader(resStream); string result = reader.ReadToEnd(); resStream.Close(); logger.Debug(result); reader.Close(); } catch (Exception e) { logger.Error("画像レスポンス待ち失敗 message=" + e.ToString()); throw e; } logger.Info("画像レスポンス待ち終了"); } /// <summary> /// パスのファイルを開きバイナリデータを取得する /// </summary> /// <param name="path"></param> /// <returns></returns> private byte[] GetImageBinaryData(string path) { if (path == null) { throw new ArgumentNullException("パスがnull"); } if (!File.Exists(path)) { throw new FileNotFoundException("指定されたパスにファイルが存在しない path=[{0}]", path); } logger.Info("画像ファイル読み込み開始"); logger.Info(" path=" + path); byte[] data; try { FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read); long size = stream.Length; data = new byte[size]; stream.Read(data, 0, (int)size); stream.Dispose(); } catch (Exception e) { logger.Error("画像ファイル読み込み失敗 message=" + e.ToString()); throw e; } logger.Info("画像ファイル読み込み終了 path=" + path); return data; } /// <summary> /// アップロード用XML作成 /// </summary> /// <param name="data">画像バイナリデータ</param> /// <param name="title">画像タイトル</param> /// <param name="folder">画像フォルダ</param> /// <returns></returns> private string MakeUpdateXML(byte[] data, string title, string folder = "") { logger.Info("はてなフォトライフアップロード用XML作成開始"); logger.Debug(" title =" + title); logger.Debug(" folder =" + folder); logger.Debug(" datalen=" + data.Length); if (data == null) { throw new ArgumentNullException("データがnull"); } if (data.Length <= 0) { throw new ArgumentException("データが空"); } if (title == null) { throw new ArgumentNullException("タイトルがnull"); } if (folder == null) { throw new ArgumentNullException("フォルダがnull"); } StringBuilder buffer = new StringBuilder(); buffer.Append("<entry xmlns=\"http://purl.org/atom/ns#\">\n"); buffer.Append(" <title>" + title + "</title>"); if (folder != null && folder.Length > 0) { buffer.Append(" <dc:subject>" + folder + "</dc:subject>\n"); } buffer.Append(" <content mode=\"nonce64\" type=\"image/jpeg\">"); buffer.Append(Convert.ToBase64String(data)); buffer.Append("</content>\n"); buffer.Append("</entry>"); logger.Info("はてなフォトライフアップロード用XML作成終了"); #if DEBUG logger.Debug(buffer.ToString()); #endif return buffer.ToString(); } private readonly HatenaAccount hatenaAccount; private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); } }
Uploadメソッドのfolder引数にフォルダ名を指定すると、同名のフォルダがすでにある場合は、そのフォルダに画像が配置。同名のフォルダがない場合は、新規作成した上で画像が配置されます。
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Harunakasoft.Library; namespace HatenaPhotoLifeTest { class Program { static void Main(string[] args) { try { HatenaPhotoLifeUploader uploader = new HatenaPhotoLifeUploader("name", "password"); uploader.Upload(@"C:\Users\kanaharu\Desktop\reimu_twitter.jpg", "test"); } catch (Exception e) { Console.WriteLine(e.ToString()); } } private static readonly log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); } }