LoginSignup
16
16

More than 5 years have passed since last update.

標準コマンドだけでファイルを送りあえるサーバーを作ってみました

Last updated at Posted at 2017-12-03

はじめに

他のデバイスへのファイル転送の煩わしさを少しでも解消できたらと思い作りました
MacユーザーならAirDropでとすんなりいけるのですが、他のユーザーだと、Slack、LINEとかを使ってのファイル転送で、それもなければメールで... と面倒です

ターミナルと使ってると、他のブラウザなりGUIを立ち上げるの面倒なのです。なのでコマンドで送れるように考えました
加えて、新しくコマンドをインストールせずに、標準的なコマンドだけで送れる方法を考えました

特徴

  • 標準的なコマンドcurlwgetがあれば、ファイル送受信できる
  • アカウントを作る必要がない
  • ブラウザからでも送受信できる

ファイルを送る

以下は./test.txtを送る例です

cat ./test.txt | curl -T - https://trans-akka.herokuapp.com/

Dec-03-2017 18-45-48.gif

ファイルを受け取る

以下の方法でダウンロードできます。
cwmはFile IDです。送信したときのレスポンスのランダムな文字列です(後述のオプションでセキュリティのレベルを向上させることができます)。

curl https://trans-akka.herokuapp.com/cwm > myfile

Dec-03-2017 18-46-59.gif

(上記のURLにアクセスすれば、ブラウザからでもダウンロードできます)

その他の使い方

詳しい説明は、下の方の「その他の特徴」をご覧ください。

GitHubリポジトリ

GitHub: nwtgck/trans-server-akka

公開サーバー

Dockerでサーバーを立てる

docker run一発ですぐに立てれます。

docker run -it -p 8080:80 nwtgck/trans-server-akka:v1.19.6 --http-port=80

これで、http://localhost:8080 にサーバーが立ちます。

データの永続化 - Docker

/trans/db内にファイルデータもデータベースのデータもあるので、以下のコマンドで永続化するようなサーバーが立てれます

docker run -d -p 8080:80 -v $PWD/trans-db:/trans/db --restart=always nwtgck/trans-server-akka:v1.19.6 --http-port=80

現在(ver 1.19.6)では、
* ファイルは圧縮され、暗号化されて保存されます
* データベースはファイルベースのH2 Databaseを使用しています

Let's encryptでHTTPS化 - Docker

ファイル送信は安全が重要なので、Let's encryptを使った、HTTPS化の方法の紹介です。
(Let's encryptに限らず使えるとは思いますが)

FULLCHAIN=/etc/letsencrypt/live/hogehoge.io/fullchain.pem
PRIVKEY=/etc/letsencrypt/live/hogehoge.io/privkey.pem

# pkcs.p12を生成する
sudo openssl pkcs12 -export -in $FULLCHAIN -inkey $PRIVKEY -out pkcs.p12 -name mytlskeyalias -passout pass:changeit

# trans.keystoreを生成する
keytool -importkeystore -srckeystore pkcs.p12 -srcstoretype PKCS12 -destkeystore trans.keystore -deststoretype JKS -srcstorepass changeit -deststorepass changeit

# transサーバーを起動
sudo docker run -it -p 80:80 -p 443:443 -v $PWD/trans.keystore:/trans/trans.keystore  nwtgck/trans-server-akka:v1.19.6 --http-port=80 --https-port=443

FULLCHAINPRIVKEYはご自身のドメインに合わせて変更してください)

その他の特徴

ヘルプ/ サーバーバージョン

wgetとかcurlのオプションとかを忘れたときに使えそうな/helpです

curl https://trans-akka.herokuapp.com/help
curl https://trans-akka.herokuapp.com/version

(curlを使うとデフォルトで標準出力にレスポンスが出るので、curlがあるときはこっちが便利です)

ファイル削除

curl -X DELETE https://trans-akka.herokuapp.com/cwm

ダウンロード回数制限付きで送信

以下の例だと1回ダウンロードされると、自動的にファイルが消滅するになります

curl 'https://trans-akka.herokuapp.com/?get-times=1' -T ./test.txt

File IDを長くして送信

覚えやすさ優先で、デフォルトが3文字なので、長くしてセキュアにしたいときは、長さが指定できます。

curl 'https://trans-akka.herokuapp.com/?id-length=16' -T ./test.txt

削除キー付きで送信

デフォルトだと削除するときにキーがないので、File IDを知っている人はだれでも削除できるので、以下で削除用のキーを設定できます

curl 'https://trans-akka.herokuapp.com/?delete-key=mykey1234' -T ./test.txt

誰も削除できないようにする

curl 'https://trans-akka.herokuapp.com/?deletable=false' -T ./test.txt

URLを送る

HTTPのPOST送信ボディー部を内容にしているだけなので、以下のようにファイルに保存されている内容でなくても送れます

 echo "https://example.com" | curl -T - https://trans-akka.herokuapp.com

https://trans-akka.herokuapp.com/r/YOUR FILE_ID のように /r/YOUR FILE_IDを指定することでリダイレクトしてくれます。
この機能で、一定時間で消滅する短縮リンクみたいになってくれます。

zip & curl でディレクトリ送信

上のURL送信と同じように、zipでも一度圧縮したファイルを生成しなくても送れます

zip -q -r - ./mydir | curl -T - https://trans-akka.herokuapp.com

tar & curl でディレクトリ送信

以下は.tar.gz版です

tar zfcp - ./mydir/ | curl -T - https://trans-akka.herokuapp.com

Range access

高速でダウンロードできるツールを Go で実装した。で有名なpgetにも対応してます

(追記) 専用のCLI

Transのコンセプトは、標準的なコマンドで送ったり受け取ったりすることです。
ただし、専用のCLIがあったほうが便利なので、Go言語でCLIを作りました。
これでtransコマンドを使える人はtransで送って、持っていない人はwgetcurlやブラウザから送受信ができるようになり便利です。

インストール

brew install nwtgck/homebrew-trans/trans

使用法

trans send test.txt
trans get cwm
trans delete cwm

どのサーバーを使うかは以下のコマンドで設定できます。

trans use https://trans-akka.herokuapp.com

詳しい使い方は https://github.com/nwtgck/trans-cli-go や、trans -hをみてください。

サーバーサイド

サーバーサイドは、Akka HTTPデータベースは、Slickで書いています。

ストリームな感じがとてもよく、
以下のような処理が、

ファイルのバイト列 => 圧縮 => 暗号化
              => バイト数を数える(Content-Lengthで使うため)

思ったように以下のようなコードになります

RunnableGraph.fromGraph(GraphDSL.create(fileStoreSink, lengthSink)(_.zip(_)){implicit builder => (fileStoreSink, lengthSink) =>
    import GraphDSL.Implicits._
    val bcast = builder.add(Broadcast[ByteString](2))

    // * compress ~> encrypt ~> store
    // * calc length
    byteSource ~> bcast ~> Compression.gzip ~> CipherFlow.flow(genEncryptCipher()) ~> fileStoreSink
                  bcast ~> lengthSink
    ClosedShape
})

特に凝ったこともしていないですし、Akka HTTPのHigh-Levelなルーティングで、とても快適にルーティングできました。

最後に

少しでもファイルを送り合う煩わしさから開放されたら嬉しいです
あと、AkkaとかAkka StreamとかAkka HTTPとかの日本語の記事が増えてくれると嬉しいです

参考

16
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
16