2016/02/24


golang で Web アプリを作ってると画像のアップロード処理を書くことって意外と多くて、その度にググったり過去の自分の実装を調べたりして、みたいな事を繰り返してましたが go-imageupload を使うとかなり端折れる事になりそうです。

GitHub - olahol/go-imageupload: Gracefully handle image uploading and thumbnail creation.
https://github.com/olahol/go-imageupload

実装は簡素ですが、毎回自分でこれを書いてたと思うと時間が勿体ないですね。使い方も簡単で README.md から転用すると 300x300 のサムネイル画像を生成するのはこれだけになります。

package main

import (
    "github.com/gin-gonic/gin"
    "github.com/olahol/go-imageupload"
)

func main() {
    r := gin.Default()

    r.GET("/"func(c *gin.Context) {
        c.File("index.html")
    })

    r.POST("/upload"func(c *gin.Context) {
        img, err := imageupload.Process(c.Request, "file")

        if err != nil {
            panic(err)
        }

        thumb, err := imageupload.ThumbnailPNG(img, 300300)

        if err != nil {
            panic(err)
        }

        thumb.Write(c.Writer)
    })

    r.Run(":5000")
}

サムネイルとは書いてますが、サイズが指定出来るので例えばアップロード画像のサイズを均一にしたい場合にも使えます。ブラウザ側の処理も dropzone.js を使えば簡単にアップロード画面が出来上がります。

まずはサーバ側のコード。

package main

import (
    "crypto/sha1"
    "fmt"
    "time"

    "github.com/gin-gonic/contrib/static"
    "github.com/gin-gonic/gin"
    "github.com/mattn/go-colorable"
    "github.com/olahol/go-imageupload"
)

func main() {
    gin.DefaultWriter = colorable.NewColorableStdout()
    r := gin.Default()

    r.Use(static.Serve("/", static.LocalFile("./assets"true)))

    r.POST("/upload"func(c *gin.Context) {
        img, err := imageupload.Process(c.Request, "file")
        if err != nil {
            panic(err)
        }
        thumb, err := imageupload.ThumbnailPNG(img, 300300)
        if err != nil {
            panic(err)
        }
        h := sha1.Sum(thumb.Data)
        thumb.Save(fmt.Sprintf("files/%s_%x.png",
            time.Now().Format("20060102150405"), h[:4]))
    })

    r.Run(":5000")
}

アップロードされた画像を 300x300 にリサイズして、日付と sha1 のファイル名付けて保存しているだけです。files というディレクトリに保存されます。クライアント側も dropzone.js 様様です。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>あぷろだ</title>
    <link rel="stylesheet" href="dropzone.css" media="all">
    <link rel="stylesheet" href="app.css" media="all">
    <script src="dropzone.js"></script>
</head>
<body>
<form action="/upload" class="dropzone" id="dropzone"></form>
</body>
</html>

一応、マウスホバーで色変えちゃうよ的な。

#dropzone {
  background-color#afa;
  bordersolid 3px #5a5;
  color#585;
  padding20px;
}

#dropzone.dropover {
  background-color#cfc;
  color#9c9;
}
upload

便利。

Go言語によるWebアプリケーション開発 Go言語によるWebアプリケーション開発
Mat Ryer
オライリージャパン / ¥ 3,456 (2016-01-22)
 
発送可能時間:在庫あり。


2016/02/15



先日、GitHub Pages が Jekyll 3.0 になりました。

GitHub Pages now faster and simpler with Jekyll 3.0 · GitHub

GitHub Pages is now running the latest major version of Jekyll, Jekyll 3.0 , and with it, many of th...

https://github.com/blog/2100-github-pages-now-faster-and-simpler-with-jekyll-3-0

速くなったという事でとても喜ばしいのですが、良い事はそれだけではなかった。GitHub Pages を使ってのブログ作成方法については、これまでこのブログでも幾つか紹介して来ました。

Big Sky :: Jekyllで始める簡単ブログ

GithubのユーザページでJekyllが使われる様になりました。 GitHub Pages Upgraded to Jekyll 0.5.0 - GitHub I just released Jek...

http://mattn.kaoriya.net/software/lang/ruby/20090409185248.htm
Big Sky :: githubとjekyllとoctopressで作る簡単でモダンなブログ

以前、「jekyllで始める簡単ブログ」という記事を書いたのですが Big Sky :: Jekyllで始める簡単ブログ GithubのユーザページでJekyllが使われる様になりました。 GitHu...

http://mattn.kaoriya.net/software/lang/ruby/20111017205717.htm

でも作った後でコードハイライトを導入したりフィードを吐いたりしようと思うと若干手間でしたし、最初は綺麗だったフォルダ構成もだんだんとグチャグチャとして来ていました。でも Jekyll 3.0 になった事でその殆どが解決してしまいました。以前は jekyll-bootstrap を使って https://mattn.github.io を作っていましたが、これを期に全部消し去って一から作り直しました。大変かなーと思ったけど、何も大変な事が無かった。

以下、その手順をご紹介します。既にリポジトリがある方は適当に読み飛ばして下さい。

リポジトリを作る

まず GitHub でリポジトリを作ります。名称は

create repository
USERNAME.github.io

という名前で作ります。ちなみに昔は

USERNAME.github.com

だった為、リポジトリ名も com で作ったよという方が多いと思いますが、Settings のページで名前を変えても動作する事を確認しました。

rename repository

Jekyll でサイトを生成する

ruby をインストールしたあと

$ gem install jekyll

とすれば2016年2月現時点ではバージョン3が入ります。でも「Jekyll のサイトを準備する為だけに ruby を入れて、Jekyll を入れるってちょっと面倒!Golang 使わせろよ!」って人は Jedie を使うといいです。

Big Sky :: Golang で Jekyll のクローン作った。

普段 vim-jp や色んな所で jekyll を使っているのだけど、どうも遅くて困っていました。 Windows だと ruby 本体の起動も重いのに、たかだか数十ページの生成に十数秒、PCの負荷が...

http://mattn.kaoriya.net/software/lang/go/20131128182642.htm

Jedie は Jekyll と互換性がある為、Jedie を使って生成したサイトはそのまま GitHub Pages に push する事が出来ます。

※ここ重要です。

サイトの生成方法は

$ jedie new /path/to/root

の様に実行して下さい。あとは

$ git add .
$ git commit -a
$ git remote add origin git@github.com:USERNAME/USERNAME.github.io.git
$ git push origin master

USERNAME 部分はご自分のアカウントで差し替えて下さい。

とすれば簡単なサイトが出来上がります。僕もデフォルトのサイトから若干デザインに手をいれて以下のサイトを作りました。

Screw It!

jekyll-bootstrap を使ってたのだけど新規投稿が反映されない問題があったので、一旦全部消して作り直した。使ったのはお手製の jekyll clone、jedie1 jedie new ....

https://mattn.github.io/

なお、ちまちまと Jekyll を使ってマニュアル通り設定したいよ!という方は以下を参照下さい。

Using Jekyll with Pages - User Documentation

Bundler - Bundler is a package manager that makes versioning Ruby software like Jekyll a lot easier ...

https://help.github.com/articles/using-jekyll-with-pages/

Jekyll の拡張を有効にする

Jekyll 3.0 になった一番の良さはこれだと思っています。

Using Jekyll Plugins with GitHub Pages - User Documentation

GitHub Pages currently supports several Jekyll plugins: Jemoji - provides support for emoji within J...

https://help.github.com/articles/using-jekyll-plugins-with-github-pages/

_config.yml に以下の様に追加します。

gems:
    jemoji
    jekyll-mentions
    jekyll-redirect-from
    jekyll-sitemap
    jekyll-feed

Jemoji

拡張子が md (markdown) の場合、GitHub 上で使える絵文字が使える様になります。例えば :+1: であれば :+1: という画像に置き換わります。以下はその例

Jedieでサイトを作り直した。 - Screw It!

Screw It! Jedieでサイトを作り直した。 jekyll-bootstrap を使ってたのだけど新規投稿が反映されない問題があったので、一旦全部消して作り直した。 使ったのはお手製の jek...

http://mattn.github.io/2016/02/14/site-with-jedie.html

jekyll-mentions

記事内で @mattn という表記を使うと、GitHub アカウントへのリンクが作られます。上記の記事内で @mattn がリンクになっているのを確認下さい。

jekyll-redirect-from

GitHub Pages は markdown で書くのですが、デフォルトではファイル名がタイトルになります。もちろん以下の様に書くことでタイトルは置き換えられるのですが

---
layout: post
title:  Jedieでサイトを作り直した。
---
jekyll-bootstrap を使ってたのだけど新規投稿が反映されない問題があったので、一旦全部消して作り直した。

使ったのはお手製の jekyll clone、[jedie](https://github.com/mattn/jedie)

```shell
$ jedie new .
$ vim _posts/2016-02-15-rebuild-site-with-jedie.md
$ git add .
$ git commit -a
$ git push origin master
```

jedie 便利。 :+1:

@mattn ++

ファイル名の先頭に付く日付を変えてしまったり、ファイル名そのものを変えてしまうと URL が変わってしまいます。この拡張を有効にしておくと、そういった場合でも古い URL から新しい URL の自動転送が有効になります。

jekyll-sitemap

この拡張を導入すると、それだけでサイトマップが自動生成されます。

jekyll-feed

これも以前は無かった機能です。以前は RSS フィードを吐き出すのに以下の様なファイルを自前で作る必要がありましたが

---
layout: nil
---
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>{{ site.title | xml_escape }}</title>
    <link>{{ site.baseurl | xml_escape }}</link>
    <atom:link rel="self" type="application/rss+xml" href="{{ page.url | xml_escape}}" />
    <pubDate>{{ site.time | date: "%a, %d %b %Y %H:%M:%S +0900" }}</pubDate>
    <lastBuildDate>{{ site.time | date: "%a, %d %b %Y %H:%M:%S +0900" }}</lastBuildDate>
    {% for post in site.posts %}
    <item>
      <title>{{ post.title | xml_escape }}</title>
      <link>{{ post.url | xml_escape }}</link>
      <guid isPermaLink="false">tag:mattn,{{ post.date | date: "%Y/%m/%d" }}:{{ post.url | xml_escape }},rev:1</guid>
      <pubDate>{{ post.date | date: "%a, %d %b %Y %H:%M:%S +0900" }}</pubDate>
      <author>mattn.jp@gmail.com (mattn)</author>
      <description>{{ post.content | xml_escape }}</description>
    </item>
    {% endfor %}
  </channel> 
</rss>

この拡張を入れるだけでフィードが自動生成されます。何それすげー便利じゃん。

あとはレイアウトファイルの head 部分を以下の様に書くだけで link タグが生成されます。

<head>
  <meta charset="UTF-8">
  <title>{{ site.title }}</title>
  {% feed_meta %}
</head>

Jekyll 3.0 でコードハイライトがデフォルトになった

以前はコードをハイライトさせる為には Google Code Prettify を使うハックが必要でした。しかし Jekyll 3.0 では rouge という highlighter がデフォルトになった為、ユーザは css ファイルだけ用意すれば良くなりました。以下は僕が使っているハイライト用の css です。

.highlight { 
  background-color#efefef;
  padding7px 7px 7px 10px;
  border1px solid #ddd;
  -moz-box-shadow3px 3px rgba(0,0,0,0.1);
  -webkit-box-shadow3px 3px rgba(0,0,0,0.1);
  box-shadow3px 3px rgba(0,0,0,0.1);
  margin20px 0 20px 0;
  overflowhidden;
}
 
code {
  font-family:'Bitstream Vera Sans Mono','Courier', monospace;
}
 
.highlight .c { color#586E75 } /* Comment */
.highlight .err { color#93A1A1 } /* Error */
.highlight .g { color#93A1A1 } /* Generic */
.highlight .k { color#859900 } /* Keyword */
.highlight .l { color#93A1A1 } /* Literal */
.highlight .n { color#93A1A1 } /* Name */
.highlight .o { color#859900 } /* Operator */
.highlight .x { color#CB4B16 } /* Other */
.highlight .p { color#93A1A1 } /* Punctuation */
.highlight .cm { color#586E75 } /* Comment.Multiline */
.highlight .cp { color#859900 } /* Comment.Preproc */
.highlight .c1 { color#586E75 } /* Comment.Single */
.highlight .cs { color#859900 } /* Comment.Special */
.highlight .gd { color#2AA198 } /* Generic.Deleted */
.highlight .ge { color#93A1A1font-styleitalic } /* Generic.Emph */
.highlight .gr { color#DC322F } /* Generic.Error */
.highlight .gh { color#CB4B16 } /* Generic.Heading */
.highlight .gi { color#859900 } /* Generic.Inserted */
.highlight .go { color#93A1A1 } /* Generic.Output */
.highlight .gp { color#93A1A1 } /* Generic.Prompt */
.highlight .gs { color#93A1A1font-weightbold } /* Generic.Strong */
.highlight .gu { color#CB4B16 } /* Generic.Subheading */
.highlight .gt { color#93A1A1 } /* Generic.Traceback */
.highlight .kc { color#CB4B16 } /* Keyword.Constant */
.highlight .kd { color#268BD2 } /* Keyword.Declaration */
.highlight .kn { color#859900 } /* Keyword.Namespace */
.highlight .kp { color#859900 } /* Keyword.Pseudo */
.highlight .kr { color#268BD2 } /* Keyword.Reserved */
.highlight .kt { color#DC322F } /* Keyword.Type */
.highlight .ld { color#93A1A1 } /* Literal.Date */
.highlight .m { color#2AA198 } /* Literal.Number */
.highlight .s { color#2AA198 } /* Literal.String */
.highlight .na { color#93A1A1 } /* Name.Attribute */
.highlight .nb { color#B58900 } /* Name.Builtin */
.highlight .nc { color#268BD2 } /* Name.Class */
.highlight .no { color#CB4B16 } /* Name.Constant */
.highlight .nd { color#268BD2 } /* Name.Decorator */
.highlight .ni { color#CB4B16 } /* Name.Entity */
.highlight .ne { color#CB4B16 } /* Name.Exception */
.highlight .nf { color#268BD2 } /* Name.Function */
.highlight .nl { color#93A1A1 } /* Name.Label */
.highlight .nn { color#93A1A1 } /* Name.Namespace */
.highlight .nx { color#555 } /* Name.Other */
.highlight .py { color#93A1A1 } /* Name.Property */
.highlight .nt { color#268BD2 } /* Name.Tag */
.highlight .nv { color#268BD2 } /* Name.Variable */
.highlight .ow { color#859900 } /* Operator.Word */
.highlight .w { color#93A1A1 } /* Text.Whitespace */
.highlight .mf { color#2AA198 } /* Literal.Number.Float */
.highlight .mh { color#2AA198 } /* Literal.Number.Hex */
.highlight .mi { color#2AA198 } /* Literal.Number.Integer */
.highlight .mo { color#2AA198 } /* Literal.Number.Oct */
.highlight .sb { color#586E75 } /* Literal.String.Backtick */
.highlight .sc { color#2AA198 } /* Literal.String.Char */
.highlight .sd { color#93A1A1 } /* Literal.String.Doc */
.highlight .s2 { color#2AA198 } /* Literal.String.Double */
.highlight .se { color#CB4B16 } /* Literal.String.Escape */
.highlight .sh { color#93A1A1 } /* Literal.String.Heredoc */
.highlight .si { color#2AA198 } /* Literal.String.Interpol */
.highlight .sx { color#2AA198 } /* Literal.String.Other */
.highlight .sr { color#DC322F } /* Literal.String.Regex */
.highlight .s1 { color#2AA198 } /* Literal.String.Single */
.highlight .ss { color#2AA198 } /* Literal.String.Symbol */
.highlight .bp { color#268BD2 } /* Name.Builtin.Pseudo */
.highlight .vc { color#268BD2 } /* Name.Variable.Class */
.highlight .vg { color#268BD2 } /* Name.Variable.Global */
.highlight .vi { color#268BD2 } /* Name.Variable.Instance */
.highlight .il { color#2AA198 } /* Literal.Number.Integer.Long */

見た目はこんな感じになります。

以前はハックを行う為にいろいろなファイルを assets に入れていましたが、Jekyll 3.0 対応を行った後はめちゃくちゃシンプルになってとても見通しが良くなりました。

GitHub - mattn/mattn.github.io: mattn.github.io

You signed in with another tab or window. Reload to refresh your session. You signed out in another ...

https://github.com/mattn/mattn.github.io

皆さんもぜひ、Jekyll 3.0 対応を行ってみてはどうでしょうか。


2016/01/30


昔から Linux でも Windows でも mpd を使ってきてる。Windows 10 にしてから環境を作ってなかったので重い腰をあげた。

まずはサーバ、これはオフィシャルが配布している Windows バイナリのまま使った。ただし Windows にログインした後毎回起動するのもうざったいし、コンソールが見えたままになるのは嫌なので nssm を使ってNTサービス化する。nssm には GUI の設定画面があるので

nssm install mpd

を実行して mpd へのパスを設定する。また設定ファイル mpd.conf は %LOCALAPPDATA%\mpd\mpd.conf に置く。mp3 は id3v2 なので filesystem_charset だけ cp932 にする。

mpd1
mpd2

ここで気を付けないといけないのは、nssm でNTサービス化した場合、Administrator で実行されこの mpd.conf のパスが教えられないので nssm の設定画面で .\mattn の様にログインユーザを設定する。

mpd3

次にクライアント側。コマンドプロンプトで生きる人なのでそのまま mpc を使う。

master/mpc.git -

wiki | mailing list/newsgroup | bug tracker | request an account Thanks to Alexander Wirt for provid...

http://git.musicpd.org/cgit/master/mpc.git/

ただし mpc のバイナリは iconv で端末のエンコーディングに変換を行ってくれないので、パッチを当てる。

diff --git a/configure.ac b/configure.ac
index 9da26be..df1adaf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -91,18 +91,11 @@ AC_ARG_ENABLE(iconv,
 
 if test x$enable_iconv = xyes; then
    AC_CHECK_FUNC(iconv,
-       [ICONV_CFLAGS="" ICONV_LIBS=""],
-       [AC_CHECK_LIB(intl, iconv,
-           [ICONV_CFLAGS="" ICONV_LIBS="-lintl"],
-           [enable_iconv=no])])
+       [ICONV_CFLAGS="" ICONV_LIBS="-liconv"])
 fi
 
 if test x$enable_iconv = xyes; then
    AM_LANGINFO_CODESET
-   if test x$am_cv_langinfo_codeset != xyes; then
-       enable_iconv=no
-       AC_MSG_WARN(nl_langinfo and CODESET not available - disabling iconv)
-   fi
 fi
 
 if test x$enable_iconv = xyes; then
diff --git a/src/charset.c b/src/charset.c
index 2e34e47..a50096d 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -26,7 +26,11 @@
 #include <string.h>
 
 #include <locale.h>
+#ifdef _WIN32
+#include <windows.h>
+#else
 #include <langinfo.h>
+#endif
 #include <iconv.h>
 
 static bool charset_enable_input;
@@ -181,9 +185,17 @@ charset_init(bool enable_input, bool enable_output)
    if (original_locale == NULL)
        return;
 
+#ifdef _WIN32
+   if (ignore_invalid) {
+        char buf[16];
+        sprintf(buf, "cp%d", GetACP());
+       locale_charset = strdup(buf);
+    }
+#else
    const char *charset = nl_langinfo(CODESET);
    if (charset != NULL)
        locale_charset = strdup(charset);
+#endif
 
    setlocale(LC_CTYPE,original_locale);
 
diff --git a/src/charset.h b/src/charset.h
index 2eca94b..67a027c 100644
--- a/src/charset.h
+++ b/src/charset.h
@@ -25,7 +25,7 @@
 #include "Compiler.h"
 
 #include <stdbool.h>
-
+#if 0
 #ifdef HAVE_ICONV
 
 /**
@@ -74,5 +74,6 @@ charset_from_utf8(const char *from)
 }
 
 #endif
+#endif
 
 #endif

これで grep 等で絞り込む時は utf-8 だけど端末に表示される時は cp932 になる(ちょっとやっつけ)。ビルドには libmpdclient が必要。

mpc listall | grep "Taylor Swift" | mpc add

して再生していたら娘がテイラースウィフトを気に入った様だ。

Be My Taylor Swift Be My Taylor Swift

Oddball Productions / ¥ 100 (2016-01-12)
 
発送可能時間:通常1~2営業日以内に発送