今日は間に合わず

 先日書いたOneDriveAPIから取得した画像サムネイルのURLがテンポラリなもので、見事に有効期限切れを起こしていた。だからOneDriveをこのブログのメインストレージに使うのはやめて、Azureのファイルストレージに切り替えるためにブログエンジン書き換え中。アドベントカレンダーネタ間に合わず。
comment: 0

バイナリ入りのデータをブラウザに返すためにJSONではなくBSONを使う

 以前にJSONにJPEGをbase64エンコードして入れてみた。だけどgzipとかで転送データ量を減らす工夫がされてる昨今で、データ量が肥大化するbase64エンコードを使うのがいただけないとひっかかっていた。なのでBSONを触ってみる。

 BSONでのHelloWorldは下記参照。公式のサンプル。
{"hello": "world"}

\x16\x00\x00\x00 // total document size
\x02 // 0x02 = type String
hello\x00 // field name
\x06\x00\x00\x00world\x00 // field value
\x00 // 0x00 = type EOO ('end of object')


 今回は手っ取り早く試したいのでPythonを使う。BSONドキュメントはPyMongo付属のものを使う。なのでPyMongoをインストール。
pip install pymongo

 BSONドキュメントを作るサンプル。
import collections

import bson


jpg_data = b"\xFF\xD8\xDD\xE0"


bson_doc = bson.BSON.encode({"jpg": jpg_data})
print(bson_doc)

 これはbase64エンコードのような数十パーセントのデータ量肥大化をしておらず、ドキュメントへのデータ一件追加につき10バイト程度で済んでいる。こっちのほうがbase64エンコードでJSONに入れるよりデータ量では合理的。

 ブラウザ側でBSONのオブジェクト化もライブラリを使えば一行。
https://github.com/mongodb/js-bson
comment: 0

ゆく年くる年

 しわす。まだ大みそかまで少しばかりあるが、今年やったことを簡単にまとめておく。おおよそ以下のところだろう。
・このブログの作成(ASP.NET Core MVC on Azure)
・GoogleAppEngineにのっけてあった個人的なアプリをコンテナで動くものに移植、Arukasでデプロイ
・↑のようなDockerの使い方の探索
・PhantomJSを使っていたけどSeleniumに手を出してみた
・ガンプラ塗ってみた
上記についてちょこちょこと書いていく。

 ASP.NET MVCがLinuxでも動くぞというふれこみで、.NET Coreがリリースされた。ぼくはこれまでにPythonの軽量なWebフレームワークしか使ったことがなかったのでこの機会に一つアプリを作るという形で触れてみた。その成果がこのブログ。ただしMVCのもっとも基本的なことであろうMVCの三機能の切り分けぐらいにしかまだ使ってない。スキャッフォルディングとかテストとかの便利機能をまだ全然使えていない。だからそのあたりも追々やっていく。

 GoogleAppEngineにのっけてあったアプリの移植。コンテナに入れてさくらのArukasを実行環境にした。Arukas自体がまだ安定してなさそうというのはあるが、個人的なものなので大した問題にはならないと思い、そこには目をつぶっている。コンテナになってしまったので、そのイメージをどこかのコンテナ実行できる環境(Docker入れたVPSやらさくらのArukasやらAzureのコンテナ使えるサービスやら)でポンのポンでデプロイできて楽。


 ↑のを一例としてDockerの使い方を探っている。他人にSQLインジェクションを試してもらうために簡単にその環境を用意できるイメージを用意したが、まだ完成度が低いのでブラッシュアップしていきたい。
https://github.com/hMatoba/SQLInjection-DockerSample

 個人的なものでやってるのとは別なところで、Webのフロントのテストが手動になっていたのが耐え難かった。それまで個人的に使っていたPhantomJSを使うことを考えたが、レンダリングやJS実行のエンジンなどの組み合わせがちょっと特殊。ナニソレとつっぱねられそうだったのでChromeやFirefoxを動かせるSeleniumを使ってみた。
https://absurd.azurewebsites.net/Article/44

 10年ぶりぐらいにガンプラを作った。プラモデル屋さんにある塗装済みのがかっこよかったのでぼくも塗装をしてみた。メタリックなキャンディカラーでメインカラーを置き換えてみるとだいぶ好みのものになった。


 今年の頭にASP.NET MVCとNode.jsやると書いた。Node.jsのほうは結局アプリを作るまでには達していない。ちょっと触ってみて、それでなにかを作ることはまだないだろうと感じたので。現状はまだNode.jsでなにかを作ることはなさそう…とか思ったけど一個ライブラリ作ってた。Nodejs初のExifの読み書き両方ができるやつ。
 Pythonで作ってあったものをJSに移植したのだけど、JSのほうがスターが多くなってきてちょいびっくり。
https://github.com/hMatoba/piexifjs

 来年は基礎固めもしたい。デザパタを抑える。あとはソフトとして触りたいのは今のところAnsible。やったことをゴリゴリとこのブログに書いていく。
comment: 0

OneDriveAPIから画像ファイルのURLを取ってくる

 OneDriveにアップロードした画像で、APIを使ってその画像にいつでもアクセスできるURLを取ってきたい。そのあたりをゴリゴリやってみたのでまとめておく。

 まず、いろいろやってみた結果として取ってこれる画像のURLでは、アップロードしたsource画像にアクセスするのは無理そうである。長辺が800px以下になるようにリサイズされたものしかとってこれなかった。

 画像URLはthumbnailデータとして取ってくる。
httpClient.DefaultRequestHeaders.Add("Authorization", $"BEARER {oauthToken}");

var id = Request.Query["id"];
var uri = $"https://api.onedrive.com/v1.0/drive/items/{id}/?select=id,name&expand=thumbnails(select=large,source)";
var response = await httpClient.GetAsync(uri);

 デフォルトのデータセットの中にもダウンロードURLが入っているが、そのURLは非永続的なものなのでぼくのほしいものではなかった。同様にthumbnailのサイズをsourceで取ってきても非永続的なURLになっているのでダメ。
 結果、画像の永続的なURLを取ってこれるのは、先に書いたように最大で長辺800pxのlargeサイズ画像ということになった。

 createLinkというのがAPIの中にあり、これ使えば共有リンク作れるでとあったので試してみたが、こっちも目的のものではなかった。
https://dev.onedrive.com/items/sharing_createlink.htm
それで返ってくるのはiframeに入ったファイルで、ワードとかエクセルのファイルで使うと便利なものだろう。今回はいらん。

 というわけで今回OneDriveから取ってこれた画像のURLは、サムネイルのものだった。欲しかったsourceの永続的なURLは取ってこれなかった。
…なんか不満だからAzureBlobを使うことを考えてみるか。
comment: 0

C#でGETやPOSTを使ってWeb API(OneDriveAPI)をつっつく

 このブログのバイナリファイルのストレージはOneDriveを使っている。そしてファイルに関するデータをそのAPIからとってきている。そこでWeb API(OneDrive)のC#でのつっつき方をまとめておく。OneDriveAPIを使うのに必要な認証は以前にやったので今回は認証のあとから入る。
認証


 まず基本となるHttpClientを用意する。これにトークンをヘッダでくっつけて以降のリクエストは行う。
var httpClient = new System.Net.Http.HttpClient();

httpClient.DefaultRequestHeaders.Add("Authorization", $"BEARER {oauthToken}");


 GETでつっつく
var uri = $"https://api.onedrive.com/v1.0/drive/items/{id}/?expand=thumbnails(select=small,source)";

var response = await httpClient.GetAsync(uri);
var responseBody = await response.Content.ReadAsStringAsync();



 POSTでJSONを投げてつっつく
var dict = new Dictionary<string, string>

{
{ "type", "embed" },
};
var json = JsonConvert.SerializeObject(dict);
var content = new StringContent(json, Encoding.UTF8, "application/json");

var uri = $"https://api.onedrive.com/v1.0/drive/items/{id};
var response = await httpClient.PostAsync(uri, content);



 POSTでmultipart/form-dataを投げるのは認証の時にやった。おさらい
var content = new FormUrlEncodedContent(new Dictionary<string, string>

{
{ "client_id", client_id },
{ "redirect_uri", redirect_uri },
{ "client_secret", client_secret },
{ "code", code },
{ "grant_type", "authorization_code" },
});
var codeResponse = await httpClient.PostAsync("https://login.live.com/oauth20_token.srf", content);
comment: 0