1
2

Nodeビギナーズブックでつまったところ(formidableのインタフェースが変わっている)

Last updated at Posted at 2024-08-16

要点

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();
	});
}

参考

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2