[C#] 画像仕分けアプリを作ってみた
どうもこんばんは!HYPのこうじです。
最近、YahooからYahooへの移行代行を請け負う事があったのですが、その時の話です。
簡単に言うとYahooショッピングをもう1店舗出店するという感じですね。
現在のYahooショッピングは多少ポイント負担分が増えたとはいえ、楽天等と比べても比較的リーズナブルっていうか殆どタダに近いです。
そういう事もあって、もし店舗内にごちゃごちゃと商品が入り混じっているよりかは、商品のコンセプトによって振り分けてイメージに合ったサイト作りをするだけでも若干売れ行きも変わることがあるようです。
そんなこんなで、モールのデータ移行と言えば流れとしては、大体こんな感じ。
- 新規店舗の初期設定を行う。
- カテゴリーデータをアップロード。
- 移行元店舗から、実際に移行する商品を選ぶ。
- 不思議なチカラを使って、データ内URLを新規店舗用に置き換える。
- 商品データCSVをアップロード。
- 不思議なチカラを使って、使用画像を全て抽出。
- 商品画像をアップロード
画像アップロードで困った
みなさんお気づきかもしれませんが、ストアクリエイターPROの画像一括アップロードの最大容量は25MBまでなんです。
2~300ファイルくらいならまぁポチポチ25MBずつ分けて圧縮してあげようかな~とか考えてましたが、そんな優しいファイル数ではありませんでした。
- こ、これは眠くなる…
- と言うよりこんな生産性の無い作業したくない…。
- せや!機械にやらせたろ!
と言うわけで、25MB毎に振り分けて圧縮するアプリを作ってみました!
い、一応時間シミュレーションしてるから、『制作時間でアップロード終わるんじゃね?』なんて事は無いよ!!
アプリ作成開始
まずはどういう風に作ろうかな
今回のコンセプトはこんな感じです。
- 元ファイルは一切変更しない。
- 区切るバイト数を選択出来るようにする。
- ごにょごにょしやすいように、フォルダにすべて仕訳け。
- 開始前に出力先は初期化する。(いっつも消し忘れてごっちゃになるので)
- 頑張らない。
デザイン設計
途にも角にも画面が無いので始まらないので作ります。
出来上がりはこちら。
ファイルを選ぶためのボタンと、区切るバイト数を入力する欄。そして出力ボタン。これだけあれば実現出来ますね!
さて打ち込みを開始してきましょう!
打ち込み開始!
ファイル選択処理
ファイル処理選択には『OpenFileDialog』クラスが便利です。
フォームアプリの場合はそのまま使えますが、WPFアプリの場合は『Microsoft.Win32』の参照が必要です。
フォームアプリ慣れしている人には何気にブービートラップです。最初無いのかと思ってました。
今回は複数ファイル選ぶ可能性があるのと、画像以外選んでほしくないので、フィルタをかけます。
[csharp]
var dlg = new OpenFileDialog();
dlg.Multiselect = true;
dlg.Filter = "画像ファイル(*.jpg;*.gif;*.png)|*.jpg;*.gif;*.png";
[/csharp]
選択したら、選択ファイルパスを適当な変数に格納しておきます。
区切るバイト数の処理
区切るバイト数の入力は特に何もいらないですが、せっかくなので、数値以外入力出来ないようにします。
正直出力処理前に、数値かどうか判断させればいいので、完全に自己満足です。
出力ボタン処理
データが正しいかチェック
まず、処理前にデータが正しいかチェックさせます。
チェックする内容は下記の内容です。
- ファイルは選択されているか?
- 区切りバイト数は入力されているか?
全てのファイルを参照
上記がそろったら、全てのファイルパスを回してファイルの存在を確認しています。
ファイル選択した後、そのファイルが削除されていたり移動されてるかもしれないからです。
『かもしれない』運転は大事。
仕組みとしてはこんな感じ。
- 合計ファイルサイズが指定バイト数に達するまでコレクションに追加。
- 合計ファイルサイズが指定バイト数を上回る場合、新しいコレクションを作成して新規追加。
- 圧縮用にディレクトリパスも格納(今回の機能の仕様ではいらんかった)
[csharp]
string = "振り分けを保存するフォルダパス";
int index = 0;
int limitByte = 1024 * 1000 * 設定メガバイト;
var siwakeBytes = new Dictionary<int, int>() { { index, 0 } };
var siwakeFiles = new Dictionary<int, List<string>>() { { index, new List<string>() } };
var siwakeDirectories = new Dictionary<int, string>() { { index, Path.Combine(CompressDirectory, index.ToString()) } };
//
// 全ての選択ファイルパスをループ。
//
foreach (var item in CompressFiles)
{
if (!System.IO.FIle.Exists(item))
{
//
// ファイル情報を取得。
//
var fi = new FileInfo(item);
//
// ファイル数が限界突破してしまう場合は、新しくインデックスを作成して追加。
//
if ((fi.Length + siwakeBytes[index]) > limitByte)
{
index++;
siwakeBytes[index] = 0;
siwakeFiles[index] = new List<string>();
siwakeDirectories[index] = System.IO.Path.Combine(CompressDirectory, index.ToString());
System.IO.Directory.CreateDirectory(siwakeDirectories[index]);
}
//
// ファイルを仕分ける。
//
siwakeBytes[index] += (int)fi.Length;
siwakeFiles[index].Add(item);
System.IO.File.Copy(item, System.IO.Path.Combine(siwakeDirectories[index], System.IO.Path.GetFileName(item)), true);
}
}
[/csharp]
振り分けたフォルダを圧縮する
振り分けが終わったら、全部のフォルダ内容を圧縮。
圧縮には『ZipFileクラス』で簡単に可能です。便利な世の中になりましたね!
ちなみにZipFileクラスは『System.IO.Compression』の参照が必要です。
完成!さっそく使ってみる
とりあえず約9000画像ファイルを振り分けてみたいと思います!
25ギリギリだと不安だったので、24MBにして出力してみました。出力値設定できるようにしといてよかった!
上手くいくかな!?
固まった…。
ちゃんと出力された!
数十秒で終わりました!これは楽ちん!
微妙に何枚か入るんじゃないか?っていう微妙な容量になってますが気にしない。
結局アップロードは変わらない
まぁ今更ですが、ただ仕訳して出すだけなのでアップロードは手動です。
しかもストアクリエイターProのアプロダは、『誰かがアップロード中はアップロードできない』という素晴らしく舐めた機能付きなので、片手間でのんびりアップロードしていくしかありません(笑)
ちなみにこの後、追加で5800ファイルありました。作ってよかった!
終わり
これで同じような案件来ても、げんなりしなくて済みそうです!
今回も前回同様コピペで使えるとかじゃないですが、使いようによってはラク出来るよっていうのを伝えたかったんです。
あと自分とか身内で使う用だと、あまり体裁を気にしなくてもいいのがラクですね!
余談ですが、この前たまたまC#6.0の新機能動画みたら『めちゃくちゃ楽そう!』とか思いました。
未だにコードが冗長な石器人ので、その前にラムダ式とかLINQとか使いこなしたいですね!頑張ります!