【问题标题】:Downloading phar with nodejs. Which encoding should be used?使用 nodejs 下载 phar。应该使用哪种编码?
【发布时间】:2018-01-27 11:28:05
【问题描述】:

我正在尝试使用 node.js 中的程序下载 phar(PHP 存档)。经过一些测试,我发现从浏览器和 node.js 下载的文件不一样。

我尝试了一些方法:
“二进制”编码
“utf8”编码
这些都不起作用。

有人知道我应该使用哪种编码来下载 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

【问题讨论】:

    标签: php node.js phar


    【解决方案1】:

    我注意到原始代码中的一些问题:

    • 主要问题是二进制数据被隐式转换为 UTF-8 字符串,这将保留内容。将数据保存在Buffer 表单中只需使用流将响应通过管道传输到磁盘,而不是先在内存中缓冲整个响应。

    • 在节点中使用异步回调时,按照惯例,您将实际的Error 对象作为第一个参数而不是字符串传递。很多时候,这些对象提供了更多信息,或者不包含在消息本身中,或者不能从错误消息中轻松解析(例如堆栈跟踪、libuv 错误代码、上下文信息,如 http URI、文件路径、主机名等) .

    • 在将响应保存到磁盘之前未检查 200 状态代码。您最终可能会将错误 html 页面(例如 400、404 等)保存到磁盘而不是您所期望的。您还应该检查 Content-Type 标头是否是您所期望的,以进一步确保响应是您认为的。

    前两项固定的示例是:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2012-01-13
      • 2016-03-15
      • 1970-01-01
      • 2012-04-24
      • 1970-01-01
      相关资源
      最近更新 更多