【问题标题】:How to download an image with Nodejs, when its URL doesn't contain the file extension?当其 URL 不包含文件扩展名时,如何使用 Nodejs 下载图像?
【发布时间】:2018-08-12 16:21:53
【问题描述】:

我正在用 Nodejs 构建一些网络爬虫。刮板可以做的一件事是下载图像。一切都很好,直到我尝试抓取一个网站,其图片不包含 url 中的文件扩展名,例如:https://example.com/images/someimagewithoutextension

这是我正在使用的小库中的一些代码,用于下载和保存图像:

 options.encoding = null

request(options, (err, res, body) => {
if (err) {
  return onError(err, done)
}

if (body && (res.statusCode === 200 || res.statusCode === 201)) {
  if (!path.extname(options.dest)) {
    options.dest = path.join(options.dest, path.basename(options.url))
  }

  fs.writeFile(options.dest, body, 'binary', (err) => {
    if (err) {
      return onError(err, done)
    }

    if (typeof done === 'function') {
      done(false, options.dest, body)
    }
  })
} 

所以,当图片 URL 缺少扩展名时,我会收到如下错误:

错误:ENOENT:没有这样的文件或目录,打开 'C:\Users\someuser\Desktop\nodescraper\images\somefilenamewithoutextension'

当我 console.log() 响应的“正文”时,我得到一些缓冲区数组(因此我无法检查 mime 类型或类似的东西),据我了解,这表示一个流.当我从请求配置中删除 encoding:null 时,我得到了一组字符,但节点实际上崩溃了。

我怎样才能保存这些图像?

【问题讨论】:

    标签: node.js stream request


    【解决方案1】:

    ENOENT

    来自node.js docs

    ENOENT(没有这样的文件或目录):通常由 fs 操作引发,表示指定路径名的组件不存在 - 给定路径找不到实体(文件或目录)。

    此外,如果文件名包含任何 restricted characters(例如 ?),则可能会发生此错误,因此建议删除或替换这些字符以确保您的应用程序运行时没有任何错误。检查 npm 上的 sanitize-filename 包。

    检测扩展

    HTTP Content-Type 响应标头包含响应正文的mime-type。因此,您可以使用它来检测您正在下载的文件扩展名。例如,如果您获得 image/jpeg 的内容类型,则文件扩展名可以是 .jpeg。 npm上还有一堆libraries可以将mime类型转换为文件扩展名。

    完整示例

    const { writeFile } = require('fs');
    const { extension } = require('mime-types');
    const { basename, extname, join } = require('path');
    const request = require('request');
    const sanitize = require('sanitize-filename');
    
    const dest = join(__dirname, 'images');
    const url = '<URL>';
    
    request({ url, encoding: null }, (error, response, body) => {
        if (error || response.statusCode < 200 || response.statusCode >= 300) {
            console.error('Request failed!');
            return;
        }
    
        let fileName = join(dest, sanitize(basename(url)));
        if (!extname(fileName)) {
            const contentType = response.headers['content-type'];
            const ext = extension(contentType);
    
            if (ext) {
                fileName += `.${ext}`;
            } else {
                console.error('Cannot detect file extension!');
            }
        }
    
        writeFile(fileName, body, (err) => {
            if (err) {
                console.error(err);
                return;
            }
    
            console.log('done');
        });
    });
    

    【讨论】:

    • 谢谢,我已经解决了我的问题。所以是的,有两个问题:从内容类型中获取扩展,就像你做的那样;删除非法字符(我使用了一个库)。现在一切正常:D
    猜你喜欢
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 2012-01-10
    • 2012-08-24
    • 2020-11-11
    • 1970-01-01
    相关资源
    最近更新 更多