Nextjsから複数の画像ファイルをポストして、NestjsのControllerで受け取る時に、受け取り方に戸惑ったので書いておきます。
Nextjsから画像FileをPOSTする
useStateでFileを保持しておきます。
File[]として、複数の画像を配列として格納します。
const [images, setImages] = useState<File[]>([])
imagesで保持しているFile[]をfetcher関数へ渡します。
POSTでは、Bodyにパラメーター(params)と、画像ファイル(images)を含めるようにします。
accessTokenや、APIに必要なキーなどは必要に応じて引数に追加します。
ポイントは、APIの受け口では配列で画像ファイルを受け取りたいので、images:File[] をファイル単位でFormDataに格納する必要があることです。
export const postImages = async (
accessToken: string,
params: ParamsDataType,
images: File[]
): Promise<responseInterface<void>> => {
const formData = new FormData()
for (const [key, value] of Object.entries(images)) {
formData.append('imageFiles', value)
}
formData.append('postData', JSON.stringify(params))
return await fetcher(`${process.env.NEXT_PUBLIC_API_BASE_URL}/post`, {
method: 'POST',
headers: {
Authorization: `Bearer ${accessToken}`
},
body: formData
})
}
fetcher関数は、Fetch APIを利用しています。
export const fetcher = async (resource: RequestInfo, init?: RequestInit): Promise<any> => {
try {
const res = await fetch(resource, init)
return Object.assign(await res.json(), { statusCode: res.status })
} catch {
throw new Error()
}
}
Nestjsから画像Fileを取得する
画像を受け取るためには、FileFieldsInterceptorデコレーターを使用します。
FileFieldsInterceptorデコレーターは引数にnameプロパティを指定します。POSTする側のFormDataのキー名が一致する必要があります。
FileFieldsInterceptorデコレーターを使用する場合は、UploadedFilesデコレーターを利用して、リクエストからファイルを抽出します。
こうすることで、POSTされてきたパラメーターとファイルが取得できます。
@POST() デコレーターでPOSTを受け付けるようにします。
@ApiBearerAuth() ではNestjsで認証を入れている場合は入れて下さい。
@POST()
@ApiBearerAuth()
@ApiProduces('charset=utf-8')
@UseInterceptors(FileFieldsInterceptor([{ name: 'imageFiles' }]))
async postMethod(
@Body() data: { postData: string },
@UploadedFiles()
files: {
imageFiles: Express.Multer.File[];
},
): Promise<void> {
const postData = JSON.parse(data.postData);
const imageFiles = files.imageFiles;
}
Nestjsのファイルアップロードの公式はこちらです。
Summary
うまくPOSTができないときは、フロントエンドとバックエンドでどちらに原因があるのか詰めるところから始める必要があります。
今回はPOSTMANでファイルを添付してバックエンドAPIを叩くと動作はしたので、フロントエンドからのAPIの叩き方を見直すことでNextjsからPOSTされた画像ファイルをNestjsで受け取ることができるようになりました。