読者です 読者をやめる 読者になる 読者になる

angularjsからspringbootに画像を送信する3つのパターン

Monaca上で動いているangularjsからspringbootにファイルを送信するパターンを3つご紹介します。
まだまだあると思うけど、これで満足。

環境はこんな感じです。
Monaca : 2.0.4
onsen-ui :1.3.14
springboot : 1.3.1.RELEASE

formから送る場合

クライアント
<form id="form" enctype="multipart/form-data">
	<input type="file" id="file" name="file" />
</form>
$scope.imgFormSendServer = function() {
  var form = document.getElementById("form");
  var fd = new FormData(form);

  $http.post(
    "http://localhost/image/form",  // URL
    fd, // パラメータ
    {headers:{"Content-type":undefined} ,transformRequest:null} // オプション
  ).success(function() {
    console.log("success");
  }).error(function() {
    console.log("error");
  });
}

htmlにform情報を記載し、
jsでそのFormをFormDataの引数に渡して送信します。

その時angularjsでヘッダー情報に以下が必要とのことです。

{headers:{"Content-type":undefined} ,transformRequest:null}

こちら参考にさせていただきました。ありがとうございます。

AngularJSでFormDataをPOSTする(ファイルのアップロードする) - Qiita

サーバ
@RequestMapping(value = "image/form", method = RequestMethod.POST)
public @ResponseBody Object imageForm(
  @RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {

  log.info("name={} , length={}", file.getName(), file.getBytes().length);
  return null;
}

型をMultipartFileに、
RequestParamのパラメータ名に"file"を指定してあげます。
(アノテーションの引数は変数名がfileになっていれば必要ありません)


input=fileから送る場合

「formから送る場合」をちょっと変えます

クライアント
<input type="file" id="file" name="file" />
var file = document.getElementById("file").files[0];
var fd = new FormData();
fd.append("file", file);
$http.post(..... // あとは同じです

html側でformがなくなり、代わりにjs側でファイルの指定をすればOKです。
サーバ側は同じです。


byte[] で送る場合

こちら参考にさせていただきました。ありがとうございます。

AngularJSでファイルをアップロードする - Qiita


new FileReader()を使ってreader.resultを取得するとbase64の値が取得できます。
その値を「fd.append("file", べーす64の変数);」として格納し、
サーバ側で「@RequestParam("file") byte[] b」の形で取得できます。

(データが消えたのでこのくらいの説明で。。。)


その他学んだこと

サーバ側でファイル以外の引数を取得する

FormDataのappendを使って送信する場合、サーバ側でファイル以外の引数を受け取ることが可能です。
クライアント側「fd.appendの第一引数」とサーバ側「RequestParamの引数」が同じであればOKです。

抜粋します。

クライアント

var fd = new FormData();
fd.append("file", file);
fd.append("arg", "custom parameter");

サーバ

@RequestParam("args") String args
input=typeを消す

UIがイケてないinput=typeを消して自作ボタンでファイル取得できます。

<input type="file" id="file" name="file" style="opacity:0;" />

opacityを0にすると消えます。(ヤッター)
あとはjs側でトリガーを設定してあげればOKですね。

jQueryの例

$('#file').trigger("click");


最初サーバ側でspringのExceptionをはきまくってなんでかなーと思いましたが、
クライアント側でMultipartFileに対応したフォーマットを作らないといけないんですね。

MultipartFileの場合、受信するキー名が分かりづらいので、
ChromeのdevtoolなどでNetworkの情報をみると理解しやすいと思います。




Monaca使ってるのでCordovaプラグインが使えますが、あえてHTML側の機能でやってみました。


たぶん業務で使う場合はUIをカスタマイズしたCordovaプラグインを使い、
使えない場合は今回のHTML側で対応、とかの分岐にするのがよいんではないかと思います。

または旧デバイス向けのangularjsの高性能なプラグインを使うとかですね。




おわり

※書いてて気づいたけど正確なangularjsではありませんでしたごめんなさい。

javaコンパイルで環境の違いを吸収する

1. macでmvnコマンドを使ってビルドし、warファイルを作成
2. linuxにアップして起動

ということをしたいが、ログの中身やレスポンスの日本語が????になった。


いろいろ記事探してみるとビルド環境(=macだけ)のビルド時の文字コードを変更すると書いてあったが、
linux上の文字コードもおかしい場合がある(私がそうでした。)
ローカルとサーバ(の起動ユーザ)両方で実行してあげればOK。

export JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF-8


こちらの記事と先輩の助言を参考にさせていただきました。

Mac OS X Lion で javac コマンドが文字化けするのを直す - 今日もスミマセン。

ありがとうございます。。。ありがとうございます。。。

意味のないことを書いてみる

ぺけれっつのぱー
はっぱふみふみ

logbackでch.qos.logbackのログが消えない

logbackの設定を書いている時に「ch.qos.logback」ではじまるクラス群の初期化ログを消したい。。。
ってことをしたい時にはまった。

AsyncAppenderの定義時にrefを一つずつ定義しないとダメなようだ。

<!-- 動かない -->
<appender name="ASYNC_PATTERN" class="ch.qos.logback.classic.AsyncAppender">
	<appender-ref ref="LOG_FILE_PATTERN" />
	<appender-ref ref="ERROR_LOG_FILE_PATTERN" />
</appender>
<!-- 動く -->
<appender name="ASYNC_PATTERN_LOG" class="ch.qos.logback.classic.AsyncAppender">
	<appender-ref ref="LOG_FILE_PATTERN" />
</appender>
<appender name="ASYNC_PATTERN_LOG_ERROR" class="ch.qos.logback.classic.AsyncAppender">
	<appender-ref ref="ERROR_LOG_FILE_PATTERN" />
</appender>

こんな感じ
logback.xml · GitHub

Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext

Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext

起動時にこのエラーが出て起動出来ず。
結局根本原因が分からないけどmavenの依存関係から「javax.servlet」を外したら直った。

(直接インポートしていない場合でもどこかのライブラリが参照している場合があるのでexcludeすればOK)

前も起こったことあるけどこれなんなんだろ。。。

そのようなファイルやディレクトリはありません

linuxでデーモン登録しようとすると怒られる

[root@dev]# ln -s test /etc/init.d/test
[root@dev]# chkconfig --add test
サービス test に関する情報の読み込み中にエラーが発生しました: そのようなファイルやディレクトリはありません

シンボリックリンク絶対パスで登録しないといけんみたい

[root@dev]# ln -s /usr/local/test/test /etc/init.d/test
[root@dev]# chkconfig --add test