LoginSignup
0
0

More than 1 year has passed since last update.

Axios × Rails 複数の画像を非同期通信で楽天FTPサーバにアップロードする

Last updated at Posted at 2022-05-19

前提

仕事で楽天FTPサーバに画像をアップロードする作業ができてしまって、毎回FTPソフト開くのが面倒だなと思い簡単なウェブアプリを作りました。

完成品

ファイルを選択し、アップロードボタンを押すだけ。あとはRailsくんが頑張ってFTPにあげるのを待つのみ。
画像は1枚でも複数枚でも対応できます。
スクリーンショット 2022-05-19 21.05.32.png

この記事で言及しないこと

  • 上記の画像プレビュー機能(new FileReaderとかreadAsDataURLでググると良記事がたくさん出てきます)
  • フロントはVue3で書いています。@changeとか文法的なことは説明しない。
  • axiosの使い方

フロント

html

<label for="image-uploader">ファイルを選択</label>
<input type="file" multiple accept=".jpg"
    id="image-uploader" style="display:none;"
    @change="onFileChanged"
/>
...
<button @click="uploadToFTP">アップロード</button>

multiple: 複数のファイルを選択できるようにする
accept=".jpg": .jpg画像のみ受け付ける
style="display:none;": ファイル選択の窓は<label>で発火させているので隠す
@change="onFileChanged": ファイル読み込み終わったらonFileChanged関数を呼ぶ

JavaScript

const formData = new FormData(); // ......A
// データを準備
function onFileChanged(e) {
    const files = e.target.files; // ......B
    [...files].forEach((file) => { // ......C
        formData.append("images[]", file); // ......D
    })
}
// アップロードした画像をFTPにあげる
function uploadToFTP() {
    axios.post("/Rails側で決めたパス", formData) // ......E
}

A
非同期的にデータを送るのでformDataをまずnewします。
B
読み込んだ画像データはe.target.filesから取り出します。
C
取り出したfilesの中から画像データを一件ずつformDataに追加します。しかしこのfilesFileListという型のオブジェクトで、forEachが使えません。なのでスプレッド構文で配列に変換します。
D
formDataに画像データを入れます。images[]の”[]”が味噌です。
後ほどRails側のparamsからparams[:images]で受け取ったものをeachで繰り返し処理できるようになります。
”[]”が抜けると画像データ一件しか入らなくなります。
ここを参考:MDN-FormData.append()
E
axiosでPOSTします。
urlは自分で決めたルートで大丈夫です。(/api/upload/upload_imageとか)

バックエンド

Rails(コントローラ)

routes.rbなどは割愛します。

def upload_image
    # ftpインスタンスを生成し、ログイン
    ftp_host = 'upload.rakuten.ne.jp'
    ftp = Net::FTP.new(ftp_host)
    ftp.login(user = "xxx", passwd = "yyy")
    
    # 画像用フォルダーを作る(「すでにそのフォルダーが存在してます」のエラーが起こりがちなので、エラーハンドリングをちゃんと書いた方がいいかも)
    ftp.mkdir("/cabinet/images/xxxxxxx")

    # 作業対象のフォルダーに入る
    ftp.chdir("/cabinet/images/xxxxxxx")

    # 画像をアップロード
    image_files = params[:images]
    image_files.each do |image|
        ftp.putbinaryfile(image, image.original_filename)
    end

    # ログアウト
    ftp.close
end

FTP関連のメソッドはここ公式Docを参考しました。

おわりに

formData.append("images[]", file);のところ"[]"をつけるのが全然分からず苦労した。
次はアップロードの進捗バーとか、アップロード先をフロントで指定するなど色々実装したいのですが、今日はここまでです。

0
0
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
0
0