Reactで react-dropzone と axiosを使ってファイルアップロードを実装してみる(バックエンドはRails)

Reactで react-dropzone と axiosを使ってファイルアップロードを実装してみる(バックエンドはRails)

Reactで react-dropzone と axiosを使ってファイルアップロードを実装してみる(バックエンドはRails)

Reactで react-dropzone と axiosを使ってファイルアップロードを実装してみる(バックエンドはRails) へのコメントはまだありません

はじめに

Reactでファイルアップロードを実装してみたくて、どのような方法があるのか調べてみた。
あまり深く調べてはないが、1つめに良さそうだと感じた react-dropzone を使ってみたら、
これがかなりいい!!

あまりに気に入ってしまったので、react-dropzoneでアップロード対象のファイルを選んで、
axiosでPOSTして、サーバーサイドのRailsでファイルを保存するところまでをざっと紹介します。
Reactのことは分かっている前提ですすめますので、あしからず。

出来上がりのイメージはこんな感じ
画面左上に ファイルをドロップする場所があり、その右側にドロップされたファイルを列挙する場所がある。
で、画面下部にアップロード対象ファイルのプレビュー表示。

dropzone-2

npm で必要なものをインストール

[bash]
$ npm install –save react-dropzone axios

[/bash]

アップロード画面実装

一気に貼り付けちゃいましたので、ざっと説明しておきます。
DropZone タグで、ドラッグドロップでファイルをアップロードできる機能が
できちゃいます。acceptプロパティで受け付ける画像の種類(ファイルの種類)を指定し、
onDropでドラッグドロップされた時の処理を実装します。

今回はonDropで受付可能なファイル、不可能なファイルを引数で受け取り、
ステートを変えて、ドロップ領域の右側にそれらのファイル名を列挙します。
と同時に、画面下部に受付可能なファイルのプレビューを表示しちゃいます。

これがいとも簡単なんです。びっくりですよ。

アップロードボタンがクリックされたら、FormData オブジェクトを作り、
そこにアップロード対象のファイルを詰め込んで、axiosでPOSTします。
たったこれだけなんですよ、ホント便利ですね。

何個のファイルがアップロードされるかは不定なので、
file_1、file_2、file_3のような連番の名前をつけておきます。

[bash]
import React from “react”
import DropZone from “react-dropzone”
import axios from “axios”
import {HOST_NAME} from “../constants/index”

class Upload extends React.Component {
constructor(props){
super(props)
this.state = {acceptedfiles: [],rejectedfiles: []}
}

handleDrop(accepted, rejected) {
this.setState({acceptedfiles: accepted, rejectedfiles: rejected})
}

handleOpenClick() {
this.dropzone.open()
}

handleUpload() {

let data = new FormData()
data.append(‘name’, ‘Tom’)
data.append(‘age’, ’28’)

let cnt = 1
this.state.acceptedfiles.map(file =>{
data.append(‘file_’ + cnt, file)
cnt+=1
})

axios.post(HOST_NAME + ‘/upload_image’, data)

}

render(){
let prev = []
this.state.acceptedfiles.map(f =>
prev.push(

)
)

return (

Hello Upload…
this.dropzone = node}
accept=”image/jpg,image/png”
onDrop={(accepted, rejected)=> this.handleDrop(accepted, rejected)}
>
ここにファイルをドロップしてください。


Accepted files…

    {this.state.acceptedfiles.map(f =>

  • {f.name} – {f.size}
  • )}

Rejected files…

    {this.state.rejectedfiles.map(f =>

  • {f.name} – {f.size}
  • )}


Preview

{prev}

)
}
}

export default Upload

[/bash]

サーバーサイドの実装

Railsの実装になります。
まず最初に渡ってきたパラメーター(:name)に従ってフォルダを作ります。
今回の例では Tomさん固定です。

で、file_1、file_2、file_3と連番でアップロードされてきたファイルを
そのフォルダに保存します。

ね、簡単でしょ。

[bash]
def upload_image
image_path = Rails.root.to_s + “/public/upload_images/” + params[:name]
FileUtils.mkdir_p(image_path) unless FileTest.exist?(image_path)

cnt = 1
while true do
break if params[“file_” + cnt.to_s].blank?
file = params[“file_” + cnt.to_s]
fname = file.original_filename

File.open(image_path + “/#{fname}”, ‘wb’) { |f|
f.write(file.read)
}
cnt += 1
end
end
[/bash]

デザインCSS

とりあえず、適当ですが、こんな感じで。

[bash]
div.uploadFile{
float: left;
width: 260px;
}

div.preview {
float: left;
padding: 10px;
border: 1px solid #cccccc;
}

br.clear {
clear: both;
}
[/bash]

あとがき

出来上がってみれば、本当に簡単に出来てしまったように見えるのですが・・・

画像をPOSTした時
Rails側で

– 422 unprocessable entity
– Invalid form authenticity token

というエラーが出て悩まされました。CSRFについては分かってるつもりだったのですが、
分かってなかったようです。
ReactでSPAを作る時なんかは JSをサーブするサーバーと、APIをサーブするサーバーが
別になると思うので、

gem rack-cors を導入して、信用できるドメインを絞り込んで APIを受け付ける。
で、CSRFは ApplicationControllerで

– protect_from_forgery with: :null_session

として、とりあえず何でも受け付けるようにする。という感じでしょうか。

About the author:

Tags:

Related Posts

Leave a comment

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

Back to Top