multerを使ってNode.js+Expressでファイルアップロードを実装する
ExpressのWebサーバで、multerを使い、クライアントからアップロードされたファイルを受信する方法です。
インストール
npm install multer
単一ファイル
サーバ側
multer.single()
で受け取ります。single()
のパラメータはFormのフィールド名です。
const multer = require('multer');
app.post('/upload-file', multer({ dest: './upload' }).single('field_file'), (request, response) => {
console.log(request.file);
try {
console.log(request.file.path);
response.sendStatus(200);
} catch (err) {
console.error(err);
response.sendStatus(500);
}
});
クライアント側
クライアント側はHTMLのFormのみで送信する方法と、JavaScriptを使って送信する方法があります。
HTMLのみ
<form action="/upload-file" method="post" enctype="multipart/form-data">
<div class="input-group">
<input type="file" name="field_file" accept=".txt" class="form-control">
<button type="submit" class="btn btn-primary">アップロード</button>
</div>
</form>
HTML&スクリプト
HTML
<div class="input-group">
<input type="file" id="uploadFile" accept=".txt" class="form-control">
<button type="button" class="btn btn-primary" onclick="sendFile();">アップロード</button>
</div>
スクリプト
function sendFile() {
const input = document.querySelector("#uploadFile");
const formData = new FormData();
formData.append('field_file', input.files[0]);
fetch('/upload-file', {
method: 'POST',
body: formData,
}).then(response => {
if (!response.ok) {
throw('ファイルのアップロードに失敗しました');
}
alert("アップロードしました")
}).catch((error) => {
alert(error);
});
}
アップロード時のサーバ側ログ
{
fieldname: 'field_file',
originalname: 'sample1.txt',
encoding: '7bit',
mimetype: 'text/plain',
destination: './upload',
filename: '52b29053a31243a768a32c1ec197ce2a',
path: 'upload/52b29053a31243a768a32c1ec197ce2a',
size: 4
}
単一フィールドからの複数ファイルをアップロード
サーバ側
multer.array()
で受け取ります。array()
のパラメータはFormのフィールド名と最大ファイル数です。
app.post('/upload-file/multi', multer({ dest: './upload' }).array('field_files', 2), (request, response) => {
console.log(request.files);
console.log(request.files[0].path);
console.log(request.files[1].path);
response.sendStatus(200);
});
クライアント側
HTMLのみ
<form action="/upload-file/multi" method="post" enctype="multipart/form-data">
<div class="input-group">
<input type="file" name="field_files" accept=".txt" multiple class="form-control">
<button type="submit" class="btn btn-primary">アップロード</button>
</div>
</form>
HTML&スクリプト1
HTML
<input type="file" id="uploadFiles" accept=".txt" multiple class="form-control">
<button type="button" class="btn btn-primary" onclick="sendFiles();">アップロード</button>
スクリプト
function sendFiles() {
const input = document.querySelector("#uploadFiles");
const formData = new FormData();
formData.append('field_files', input.files[0]);
formData.append('field_files', input.files[1]);
fetch('/upload-file/multi', {
method: 'POST',
body: formData,
}).then(response => {
if (!response.ok) {
throw('ファイルのアップロードに失敗しました');
}
alert("アップロードしました")
}).catch((error) => {
alert(error);
});
}
HTML&スクリプト2
画面上は2つのinputフィールドを用意し、スクリプトで1つのフォームデータとして送信する方法です。
HTML
<input type="file" id="uploadFiles1" accept=".txt" class="form-control">
<input type="file" id="uploadFiles2" accept=".txt" class="form-control">
<button type="button" class="btn btn-primary" onclick="sendFiles();">アップロード</button>
スクリプト
function sendFiles() {
const input1 = document.querySelector("#uploadFiles1");
const input2 = document.querySelector("#uploadFiles2");
const formData = new FormData();
formData.append('field_files', input1.files[0]);
formData.append('field_files', input2.files[0]);
fetch('/upload-file/multi', {
method: 'POST',
body: formData,
}).then(response => {
if (!response.ok) {
throw('ファイルのアップロードに失敗しました');
}
alert("アップロードしました")
}).catch((error) => {
alert(error);
});
}
アップロード時のサーバ側ログ
[
{
fieldname: 'field_files',
originalname: 'sample1.txt',
encoding: '7bit',
mimetype: 'text/plain',
destination: './upload',
filename: 'aad7d8e4f0ac4fc0ecb66d53762321d4',
path: 'upload/aad7d8e4f0ac4fc0ecb66d53762321d4',
size: 4
},
{
fieldname: 'field_files',
originalname: 'sample2.txt',
encoding: '7bit',
mimetype: 'text/plain',
destination: './upload',
filename: 'bb16d87ef2bff538d9b0f89d8268dadb',
path: 'upload/bb16d87ef2bff538d9b0f89d8268dadb',
size: 18
}
]
複数フィールドからファイルをアップロード
サーバ側
multer.fields()
で受け取ります。fields()
の各要素のnameプロパティ
がFormのフィールド名です。
app.post('/upload-file/multi-input', multer({ dest: './upload' }).fields([
{ name:'field_file1', maxCount:1 },
{ name:'field_file2', maxCount:1 }
]), (request, response) => {
console.log(request.files);
console.log(request.files['field_file1'][0].path);
console.log(request.files['field_file2'][0].path);
response.sendStatus(200);
});
クライアント側
HTMLのみ
<form action="/upload-file/multi-input" method="post" enctype="multipart/form-data">
<div class="input-group">
<input type="file" name="field_file1" accept=".txt" class="form-control">
<input type="file" name="field_file2" accept=".txt" class="form-control">
<button type="submit" class="btn btn-primary">アップロード</button>
</div>
</form>
HTML&スクリプト
HTML
<input type="file" id="uploadFile1" accept=".txt" class="form-control">
<input type="file" id="uploadFile2" accept=".txt" class="form-control">
<button type="button" class="btn btn-primary" onclick="sendFiles2();">アップロード</button>
スクリプト
function sendFiles2() {
const input1 = document.querySelector("#uploadFile1");
const input2 = document.querySelector("#uploadFile2");
const formData = new FormData();
formData.append('field_file1', input1.files[0]);
formData.append('field_file2', input2.files[0]);
fetch('/upload-file/multi-input', {
method: 'POST',
body: formData,
}).then(response => {
if (!response.ok) {
throw('ファイルのアップロードに失敗しました');
}
alert("アップロードしました")
}).catch((error) => {
alert(error);
});
}
アップロード時のサーバ側ログ
[Object: null prototype] {
field_file1: [
{
fieldname: 'field_file1',
originalname: 'sample1.txt',
encoding: '7bit',
mimetype: 'text/plain',
destination: './upload',
filename: '10b77b3a2f139e0c9313ff606e8bf715',
path: 'upload/10b77b3a2f139e0c9313ff606e8bf715',
size: 4
}
],
field_file2: [
{
fieldname: 'field_file2',
originalname: 'sample2.txt',
encoding: '7bit',
mimetype: 'text/plain',
destination: './upload',
filename: '3095e282680e22bca2dc40c3976e4214',
path: 'upload/3095e282680e22bca2dc40c3976e4214',
size: 18
}
]
}