form タグのない HTML の input 要素をつかってファイルをアップロードする方法

なんかめっちゃひさしぶりに記事書きます。 Day One でためてきゃいいわーってなってて、 アウトプットはプライベートになってました。

file upload - Sending multipart/formdata with jQuery.ajax - Stack Overflow

sample code

function hoge(formData){
  var dfd = $.Deferred();
  return $.ajax({
    url: '/api/check_icon',
    type: 'POST',
    scriptCharset: 'utf-8',
    data: formData,
    processData: false,
    contentType: false,
    dataType: 'json',
    cache : false,
    async: false
  }).then(function(res) {
    if(res.status == 'SUCCESS') {
      dfd.resolve();
    } else {
      dfd.reject();
    }
    return dfd.promise();
  }, function(e, s) {
    dfd.reject();
    return dfd.promise();
  });
}
var data = new FormData();
data.append('homeImg', $('#inputFile')[0].files[0]);
hoge(data).done(function(data){
  console.log(data);
  //after();
});

html

<input type="file" id="inputFile">

このコードでは、ID が inputFile の input['file'] で設定されているファイルを homeImg というパラメータ名でサーバに非同期処理でアップロードするサンプルです。

enctype での multipartform-data 設定はなくてもいけます。 new FormData したオブジェクトに、append で名前と input['file'] 要素をいれてるのがミソです。 ほかの文字列パラメータや複数画像ももちろん設定できます。 アップロードサイズには気をつけてください。

iOS アプリ作成時 はじめにやっておくことメモ

XCode で TODO を。。。

かんたんにできないみたい。

Xcode4のTODOタグを警告に出力する - 中継地点

Xcode3以前ではTODO等のタグコメントでファンクションメニューに表示されていましたが、Xcode4からメソッド内でのTODOタグが拾われなくなりました。

だそうで。

追加されたRun Scriptに下記のスクリプトを記述する

KEYWORDS="TODO:|FIXME:|\?\?\?:|\!\!\!:"
find ${SRCROOT} \( -name "*.h" -or -name "*.m" \) -print0 | \
    xargs -0 egrep --with-filename --line-number --only-matching "($KEYWORDS).*\$" | \
    perl -p -e "s/($KEYWORDS)/ warning: \$1/"

ってのができればいいんだが、XCode5 で設定項目を探せない。。。

How to Add a Run Script Build phase

プロジェクト設定を選択して

タブの BuildPhases

タブ内にある小さな + ボタンから New Run Script Phase

Run Script

Shell に /bin/sh

そのしたのテキストボックスにスクリプトをはりつける

あった。わかりにくいぜ・・・。


デバッグ用ログマクロ

iOS - NSLog デバッグ用の各種ログマクロまとめ - Qiita

xxx-Prefix.pch

#ifdef DEBUG
    #define LOG(...) NSLog(__VA_ARGS__)
    #define LOG_PRINTF(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
    #define LOG_METHOD NSLog(@"%s", __func__)
    #define LOG_METHOD_AND_ABORT LOG_METHOD; abort()
#else
    #define LOG(...)
    #define LOG_PRINTF(FORMAT, ...)
    #define LOG_METHOD
    #define LOG_METHOD_AND_ABORT
#endif

#ifdef DEBUG
    #define LOG_POINT(p) NSLog(@"%f, %f", p.x, p.y)
    #define LOG_SIZE(p) NSLog(@"%f, %f", p.width, p.height)
    #define LOG_RECT(p) NSLog(@"%f, %f - %f, %f", p.origin.x, p.origin.y, p.size.width, p.size.height)
#else
    #define LOG_POINT(p)
    #define LOG_SIZE(p)
    #define LOG_RECT(p)
#endif

#if DEBUG
@interface UIView (DebugPrivate)
- (NSString*)recursiveDescription;
@end
#endif

Capistrano3 をファイル転送のためだけに使ってみる

はじめに

以前メモってた ビルドツール capistrano メモ - zonote は Capitrano2 のはなしで今はもう有用ではありません。

この記事で使ってるもののバージョンとかは以下です。

$ ruby -v
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-darwin12]
$ gem -v
2.2.1
$ cap -V
Capistrano Version: 3.1.0 (Rake Version: 10.1.1)

MacCapistrano 3 をつかう

Macのruby を最新のバージョンにアップデート: rubyメモ

MacPortsのバージョンは次のコマンドで確認できます。

port -v

MacPortsはけっこう前にインストールしたので以下のコマンドで最新にしておきましょう

sudo port -d selfupdate
sudo port -d sync

以下のコマンドでインストールできるrubyの一覧を確認できます

port list ruby*

表示されたのは以下の内容

ruby          @1.8.7-p371  lang/ruby
ruby-build    @20130501    ruby/ruby-build
ruby19        @1.9.3-p392  lang/ruby19
ruby20        @2.0.0-p0    lang/ruby20
ruby186       @1.8.6-p420  lang/ruby186
ruby_select   @1.0         sysutils/ruby_select

次のコマンドでrubyの1.9がインストールできます。

sudo port install ruby19

MacPortsでインストールしたrubyは以下のコマンドで切り替えられます。

sudo port select ruby ruby19

gem 自体のアップデート

CmdNote - Search Results: tag:gem

gem update --system

Capistrano インストール

sudo gem install capistrano
sudo gem install capistrano_colors
sudo gem install capistrano-ext
sudo gem install railsless-deploy

railsless-deploy は Capistrano3 では不要なようです。

これで

cap install

ができるようになった。これは Capistrano 2.x の capify コマンドにあたるもの。

やりたいこととやるための方法

で、Capistrano 3 はずいぶんと色々かわったそうです。

わたしがやりたいことは、20台にスクリプトを配布するだけ、だったんですが何もわからずにやるとやっぱりだめですね。

入門 Capistrano 3 ~ 全ての手作業を生まれる前に消し去りたい | GREE Engineers' Blog

ここを読んでようやく雰囲気がわかった。。。

Capifile

# Load DSL and Setup Up Stages
require 'capistrano/setup'

# Includes default deployment tasks
require 'capistrano/deploy'

framework_tasks = [:starting, :started, :updating, :updated, :publishing, :published, :finishing, :finished]

framework_tasks.each do |t|
  Rake::Task["deploy:#{t}"].clear
end
Rake::Task[:deploy].clear

# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }

↑ 初心者向けデフォルトタスクの消去、ここでやるのがただしいのかわかりませんがこれで。

deploy.rb

# config valid only for Capistrano 3.1
lock '3.1.0'
set :dist_dir_name, 'dev_java_load_db'
set :dist_base_dir, '/Users/user/IdeaProjects'
set :deploy_to, '/home/ec2-user'

task :update do
  run_locally do
  end
end

# カレントパス配下にある application名のディレクトリをターボールにするだけ。
task :archive => :update do
  run_locally do
    execute "cd #{fetch :dist_base_dir}; tar -zcvf #{fetch :dist_dir_name}.tgz #{fetch :dist_dir_name}"
  end
end

# ターボールにしたファイルをサーバにアップロード。
# サーバのホームディレクトリに application名のディレクトリを作ってそこにアップ、
# 解凍して中身をホームディレクトリに展開
task :deploy => :archive do
  deploy_from = "#{fetch :dist_base_dir}/#{fetch :dist_dir_name}.tgz"
  on roles(:web) do
    unless test "[ -d #{deploy_to} ]"
      execute "mkdir -p #{deploy_to}"
    end
    info deploy_from
    info deploy_to
    upload! deploy_from, deploy_to
    execute "cd #{deploy_to}; tar -zxvf #{fetch :dist_dir_name}.tgz; rm -fr #{fetch :dist_dir_name}.tgz"
  end
end

# end

production.rb

role :web, %w{ec2-user@xxx.xxx.xxx.xxx ec2-user@xxx.xxx.xxx.xxx}
set :ssh_options, {
  keys: %w(/Users/user/.ssh/hoge.pem),
  forward_agent: false,
}

↑ WEBサーバで、ユーザ名@ホスト名 の指定を忘れないように。

実行する

cap production deploy

BasicAuth 配下での ELB の設定

WEB を全部 BasicAuth かけてるときに、ELB 配下だけは BasicAuth を外さないといけない。 そんな設定。

ELB の ping を http とかで /elb/ とかにしておく。

mkdir /var/www/html/elb/
cat << EOF > /var/www/html/elb/index.html
DEV WEB
EOF

これで ELB の生存監視用ファイルを作成。 ドキュメントルート配下すべてに BasicAuth がかかってるので、

cat << EOF > /var/www/html/elb/.htaccess
Satisfy any
order allow,deny
allow from all
EOF

これで BasicAuth を外す。

自己署名した証明書を使ってELBでSSL通信する

自己署名証明書でAmazon ELBのHTTPS接続を使用する。 | 三度の飯とエレクトロン

このリンクだけでことすむんですけどね。

コマンド

証明書ファイルをつくる。

openssl genrsa -aes128 2048 > server.org # てきとうにパスワードをいれる
openssl rsa -in server.org > server.key # パスワードを外す
openssl req -new -key server.key > server.csr # 証明書要求
openssl x509 -req -days 365 -in server.csr -signkey server.key > server.crt # 自分で署名する。ほんとは認証局にお願いする

出来上がったファイルを ELB にポチポチ入力する。

ELBHTTPS を使う設定にしておくこと。

ELBPrivate Keyserver.key

ELBPublic Key Certificateserver.crt

の内容を入力する。

これでオレオレ証明書なので警告出ますが HTTPS で通信できるようになります。

PHP のセッションを ElastiCache をつかって共有する

ELC の設定

aws コンソールから ElastiCache を選択。

Launch Cache Cluster で新しくつくる。

  • Name は適切なものに
  • EnginememcachedPHP って Redis でセッション共有大丈夫なのかな?バージョン?)
  • Cache Engine Version はデフォルトのまま
  • Node Type はメモリの大きさに関わるので適切なものに
  • Number of Nodes1
  • Cache Port11211
  • Cache Subnet Groupdefault
  • Preferred Zone は 適切なAZ
  • Topic for SNS NotificationDisable Notifications
  • Auto Minor Version Upgrade は適切な方を

  • VPC Security Group(s) は適切なものに
  • Cache Parameter Groupdefault
  • Maintenance WindowNo Preference

こんなかんじで。

セキュリティグループで 11211 ポートでの通信を EC2 インスタンスなどからできるようにしておくこと。

EndpointMemcache サーバの名前なのでメモしておく。

PHP Session で Memcache を使う

pecl から memcache をいれます。yum からでもパッケージあれば入ると思います。 aws はありそうだけどみてないです。 あと、PHP の memcache ライブラリには、memcachememcached があるので注意してください。 AWS が配布している Auto Discovery 対応のライブラリは、memcached です。 その場合、session.save_handler と extension=memcache.so が memcached にかわります。

sudo yum -y install php-devel gcc make zlib-devel php-pear httpd-devel 
sudo pecl install memcache

pecl からなので、php.inimemcache.so の設定と、セッションを file から memcache に変更します。

sudo vim /etc/php.ini

session.save_handler = memcache
session.save_path = "tcp://localhost:11211"

.
.
.

extension=memcache.so

Apachesudo service httpd restart などで設定を読み込む。 reload でもいけるんかな。

確認する

cat << EOF > /var/www/html/st.php
<?php
    session_start();
?>

<html>
<head><title>PHP TEST</title></head>
<body>

<?php

print(\$_SERVER["SERVER_ADDR"] . "<br><br>");
    if (!isset(\$_COOKIE["PHPSESSID"])){
        print('初回の訪問です。セッションを開始します。');
    }else{
        print('セッションは開始しています。<br>');
        print('セッションIDは '.\$_COOKIE["PHPSESSID"].' です。');
    }

?>

</body>
</html>
EOF

ELC の複数ノードを設定する

上述の手順では、ELC のエンドポイントを拾ってきたんですけど、これはエンドポイント=ノード1 になってるから問題なくて、複数ノードとなっている場合、エンドポイントを指定するとセッションをうまく共有できなくなってしまいます。

PHP スクリプトから ELC を使う場合は、Auto Discovery を使用するオプションを設定し、エンドポイントへの接続で問題ないのですが、セッション設定の場合、オプション指定する方法がわからなかったので今までどおり、ノードのカンマ区切りで指定します。 詳細には次の通りです。

sudo vim /etc/php.ini

session.save_handler = memcache
session.save_path = "tcp://node-1-elc:11211,tcp://node-2-elc:11211,tcp://node-3-elc:11211"

.
.
.

extension=memcache.so

これで、複数の ELC ノードを使用してセッションを共有してくれます。 まあ、セッションID からハッシュを作成し、常に同じノードをみにいくようになっているだけなのですが。

Mac に OpenCV をインストールする(だけ)

環境

  • OS X Mountain Lion 10.8.5
  • プロセッサ 2.6GHz Intel Core i5
  • メモリ 8GB 1600MHz DDR3

インストール

OSX - Homebrewを使ってMacにOpenCVを導入するまで - Qiita [キータ]

brew doctor
brew update

書かれているとおりにつまづいて、解決して、だったんだけれど、 mac-ports をインストールはできなかったのでそのまま残しておいた。

brew tap homebrew/science
sudo brew install opencv

sudo brew install opencv でエラーになった。

権限周りで

dyld: DYLD_ environment variables being ignored because main executable (/usr/bin/sudo) is setuid or setgid

だったので sudo せずに brew install opencv した。

Bash - dyld: DYLD_ environment variables being ignored because main executable (/usr/bin/sudo) is setuid or setgidを黙らせる - Qiita [キータ]

もう一度 sudo brew install opencv やると別のエラーになって、コンソールみると numpy 入れろってかいていたので、コンソールからコピペして

pip-2.7 install numpy

してみた。それから

brew install opencv

これで mac に OpenCV 入った。

これで勝つる。