要点
Nodeビギナーズブックの最後の方は当時とformidableのバージョンが違うため、そのままでは動かない。
筆者はJavaScript/TypeScript/Node.jsは全くの初心者ですので、
本記事の内容は正確ではない可能性があります。
開発環境
- Ubuntu 24.04 LTS
- node v20.16.0
- formidable@3.5.1
目次
エラー内容
requestHandlers.js
function upload(response, request) {
console.log("Request handler 'upload' was called.");
var form = new formidable.IncomingForm();
console.log("about to parse");
form.parse(request, function(error, fields, files) {
console.log("parsing done");
/* Possible error on Windows systems:
tried to rename to an already existing file */
fs.rename(files.upload.path, "/tmp/test.png", function(err) {
if (err) {
fs.unlink("/tmp/test.png");
fs.rename(files.upload.path, "/tmp/test.png");
}
});
response.writeHead(200, {"Content-Type": "text/html"});
response.write("received image:<br/>");
response.write("<img src='/show' />");
response.end();
});
}
実行結果
node:internal/errors:541
throw error;
^
TypeError [ERR_INVALID_ARG_TYPE]: The "oldPath" argument must be of type string or an instance of Buffer or URL. Received undefined
}
files.upload.pathがundefinedになってしまうため、エラーが発生している模様。
原因
筆者が使用したのformidableのバージョン(formidable@3.5.1)では、
form.parse()に渡しているコールバックの第3引数filesの要素はFileの配列になっているため、
配列の要素を指定してアクセスする必要がある。
~/.cache/typescript/5.5/node_modules/@types/formidable/index.d.ts
type Files<U extends string = string> = {
readonly [Prop in U]?: File[];
};
解決方法
requestHandlers.js
function upload(response, request) {
console.log("Request handler 'upload' was called.");
let form = new formidable.IncomingForm();
form.encoding = "utf-8";
console.log("about to parse");
form.parse(request, (error, fields, files) => {
console.log("parsing done");
// ↓↓↓ forEachで配列の要素にアクセス
files.upload.forEach((file) => {
let filePath = file.filepath;
fs.rename(filePath, "./test.png", (err) => {
if (err) {
fs.unlink("./test.png");
fs.rename(filePath, "./test.png");
}
});
});
// ↓でも動くには動いたがあまりにも汚い
//let filePath = files.upload[0].filepath;
response.writeHead(200, { "Content-Type": "text/html" });
response.encoding = "UTF-8";
response.write("received image:<br>");
response.write("<img src='/show' />");
response.end();
});
}
参考
- Node.js Upload Files 主にこちらのソースコードを参考にさせていただきました。
- Nodeビギナーズブック
- formidableのGitHubリポジトリ