NextJSでファイルアップロードの実装をしております。
構成:
フロントエンド:NextJS
バックエンド:Django(DRF)
'Content-Type': 'multipart/form-data'でファイルデータを送信していますが、バックエンドでファイルデータが変更されません。
FormDataやfetchの使い方が間違っているのでしょうか?
postmanでファイルをアップロード(Body form-dataにavatar file)して送信したときは、バックエンドのファイルデータが更新されていたので、バックエンドは間違っていないかと思います。
ぜひともご教授をお願いいたします。
・コードは必要箇所のみとなります。
・上のファイルから順番に処理が流れていきます。
pages/edit_profile.js
(画面操作用)
js
1const EditProfile = () => { 2 const [avatar, setAvatar] = useState(null) 3 4 const editAvatar = () => { 5 const fileInput = document.getElementById('avatarInput') 6 fileInput?.click() 7 } 8 9 const sendAbatar = () => { 10 if (dispatch && dispatch !== null && dispatch !== undefined) { 11 // auth.jsのedit_avatar関数へ 12 dispatch(edit_avatar(avatar)) 13 } 14 } 15 16 return ( 17 <> 18 <input 19 type="file" 20 id="avatarInput" 21 hidden={true} 22 onChange={(e) => setAvatar(e.target.files[0])} 23 /> 24 <div onClick={editAvatar}>アバターを変更</div> 25 <div onClick={sendAbatar}>登録する</div> 26 </> 27 ) 28} 29 30export default EditProfile 31
actions/auth.js
(内部操作用)
js
1export const edit_avatar = (avatar) => async (dispatch) => { 2 var formData = new FormData() 3 formData.append('avatar', avatar) 4 5 // edit_avatar.jsへ 6 const res = await fetch('/api/account/edit_avatar', { 7 method: 'PATCH', 8 headers: { 9 'Content-Type': 'multipart/form-data', 10 }, 11 body: formData, 12 }) 13}
pages/api/account/edit_avatar.js
(バックエンドへ送信)
js
1export default async (req, res) => { 2 if (req.method === 'PATCH') { 3 const formData = req.body 4 5 // バックエンドへ送信 6 const apiRes = await fetch(`${API_URL}/api/v1/auth/users/me/`, { 7 method: 'PATCH', 8 headers: { 9 Authorization: `Token ${authToken}`, 10 'Content-Type': 'multipart/form-data', 11 }, 12 body: formData, 13 }) 14 } 15} 16
このコードを実行すると、下記のように返ってきます。
'Multipart form parse error - Invalid boundary in multipart: None'
edit_avatar.jsを下記のように変更すると、送信(status 200)はうまくいきますが、画像が変更されません。
const apiRes = await fetch(`${API_URL}/api/v1/auth/users/me/`, { method: 'PATCH', headers: { Authorization: `Token ${authToken}`, 'Content-Type': 'multipart/form-data', }, formData, # bodyを削除 }) }
ぜひともアドバイスをよろしくお願いいたします。
■追記
Reactの最小構成で試したら、データが更新されました。
js
1import { useState } from 'react' 2 3function App() { 4 const [avatar, setAvatar] = useState(null) 5 6 const editAvatar = () => { 7 const fileInput = document.getElementById('avatarInput') 8 fileInput?.click() 9 } 10 11 const sendAbatar = async () => { 12 var formData = new FormData() 13 formData.append('avatar', avatar) 14 15 const res = await axios.patch( 16 'http://localhost:8000/api/v1/auth/users/me/', 17 formData, 18 { 19 headers: { 20 'Content-Type': 'multipart/form-data', 21 Authorization: `Token xxx`, 22 }, 23 } 24 ) 25 26 console.log(res.status) 27 console.log(res.data) 28 } 29 30 return ( 31 <> 32 <div>Avatar</div> 33 <input 34 type="file" 35 id="avatarInput" 36 hidden={true} 37 onChange={(e) => setAvatar(e.target.files[0])} 38 /> 39 <div onClick={editAvatar}>アバターを変更</div> 40 <div onClick={sendAbatar}>登録する</div> 41 </> 42 ) 43} 44 45export default App 46
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。