使用 nodejs 下载 phar。应该使用哪种编码?
Downloading phar with nodejs. Which encoding should be used?
我正在尝试使用 node.js 中的程序下载 phar(PHP 存档)。经过一些测试,我发现从浏览器下载的文件和从 node.js 下载的文件不一样。
我已经尝试了一些方法:
"binary"编码
"utf8"编码
None 篇论文作品。
有谁知道我应该使用哪种编码来下载 phar?
我的代码:
exports.download = function(urlStr, dest, cb) { // urlStr is the url link of the phar, dest is the destination file, and cb is the callback.
var options = {
headers: {
"User-Agent": "PSM (Pocketmine Server Manager, https://psm.mcpe.fun) User Requester"
}
}
var data = "";
var url = new URL(urlStr);
options.hostname = url.hostname;
options.path = url.pathname;
var request = http.get(options, function(response) {
// check if response is success
if (response.statusCode == 302 || response.statusCode == 301) {
exports.download(response.headers["location"], dest, cb);
return;
}
response.on("data", function(chunk) {
data += chunk.toString("binary");
})
response.on('end', function() {
fs.writeFileSync(dest, data, "binary");
cb();
});
}).on('error', function(err) { // Handle errors
fs.unlink(dest); // Delete the file async. (But we don't check the result)
if (cb) cb(err.message);
});
};
使用的 Phar(有效):https://psm.mcpe.fun/download/PSMCore/1.1.phar
我注意到原始代码中的一些问题:
主要问题是二进制数据被隐式转换为 UTF-8 字符串,这将不会保留内容。将数据保持在 Buffer
形式 或 只是使用流将响应通过管道传输到磁盘,而不是先在内存中缓冲整个响应。
在节点中使用异步回调时,按照惯例,您传递实际的 Error
object 作为第一个参数而不是字符串。很多时候,这些 objects 提供了更多的信息,这些信息要么不包含在消息本身中,要么不容易从错误消息中解析出来(例如堆栈跟踪、libuv 错误代码、上下文信息,例如 http URI、文件路径、主机名等)。
在将响应保存到磁盘之前没有检查 200 状态代码。您最终可能会将错误 [=36=] 页(例如 400、404 等)保存到磁盘,而不是您所期望的。您还应该检查 Content-Type header 是否符合您的预期,以进一步确保响应如您所想。
前两项固定的示例是:
var res;
function onError(err) {
if (res) {
res.resume(); // Ensure response is drained
res = null;
}
if (cb) {
fs.unlink(dest, function() {});
cb(err);
cb = null;
}
}
http.get(options, function(response) {
// Check if response is success
if (response.statusCode === 302 || response.statusCode === 301) {
exports.download(response.headers["location"], dest, cb);
res.resume(); // Ensure response is drained
return;
}
res = response;
var out = fs.createWriteStream(dest);
out.on('error', onError);
response.pipe(out).on('close', function() {
if (cb) {
cb();
cb = null;
}
});
}).on('error', onError);
我正在尝试使用 node.js 中的程序下载 phar(PHP 存档)。经过一些测试,我发现从浏览器下载的文件和从 node.js 下载的文件不一样。
我已经尝试了一些方法:
"binary"编码
"utf8"编码
None 篇论文作品。
有谁知道我应该使用哪种编码来下载 phar?
我的代码:
exports.download = function(urlStr, dest, cb) { // urlStr is the url link of the phar, dest is the destination file, and cb is the callback.
var options = {
headers: {
"User-Agent": "PSM (Pocketmine Server Manager, https://psm.mcpe.fun) User Requester"
}
}
var data = "";
var url = new URL(urlStr);
options.hostname = url.hostname;
options.path = url.pathname;
var request = http.get(options, function(response) {
// check if response is success
if (response.statusCode == 302 || response.statusCode == 301) {
exports.download(response.headers["location"], dest, cb);
return;
}
response.on("data", function(chunk) {
data += chunk.toString("binary");
})
response.on('end', function() {
fs.writeFileSync(dest, data, "binary");
cb();
});
}).on('error', function(err) { // Handle errors
fs.unlink(dest); // Delete the file async. (But we don't check the result)
if (cb) cb(err.message);
});
};
使用的 Phar(有效):https://psm.mcpe.fun/download/PSMCore/1.1.phar
我注意到原始代码中的一些问题:
主要问题是二进制数据被隐式转换为 UTF-8 字符串,这将不会保留内容。将数据保持在
Buffer
形式 或 只是使用流将响应通过管道传输到磁盘,而不是先在内存中缓冲整个响应。在节点中使用异步回调时,按照惯例,您传递实际的
Error
object 作为第一个参数而不是字符串。很多时候,这些 objects 提供了更多的信息,这些信息要么不包含在消息本身中,要么不容易从错误消息中解析出来(例如堆栈跟踪、libuv 错误代码、上下文信息,例如 http URI、文件路径、主机名等)。在将响应保存到磁盘之前没有检查 200 状态代码。您最终可能会将错误 [=36=] 页(例如 400、404 等)保存到磁盘,而不是您所期望的。您还应该检查 Content-Type header 是否符合您的预期,以进一步确保响应如您所想。
前两项固定的示例是:
var res;
function onError(err) {
if (res) {
res.resume(); // Ensure response is drained
res = null;
}
if (cb) {
fs.unlink(dest, function() {});
cb(err);
cb = null;
}
}
http.get(options, function(response) {
// Check if response is success
if (response.statusCode === 302 || response.statusCode === 301) {
exports.download(response.headers["location"], dest, cb);
res.resume(); // Ensure response is drained
return;
}
res = response;
var out = fs.createWriteStream(dest);
out.on('error', onError);
response.pipe(out).on('close', function() {
if (cb) {
cb();
cb = null;
}
});
}).on('error', onError);