简体   繁体   English

Node.js:下载图像之前,从请求标头获取图像文件扩展名

[英]Node.js: Get image file extension from request headers before downloading image

I am making a Node.js application used to download images. 我正在制作用于下载图像的Node.js应用程序。 When I download an image I specify the file name for the image before downloading. 下载图像时,请在下载前指定图像的文件名。 However, unlike the name I do not know what the file extension of my image will be until I read the response headers and get the content-type . 但是,与名称不同,在读取响应头并获得content-type之前,我不知道图像的文件扩展名是什么。 However, by the time I can read the response headers and create the full path for where I want the image to download to the request has already started piping the image to a blank address. 但是,到我可以读取响应标头并为要图像下载到请求的位置创建完整路径时,该路径已经开始将图像传送到空白地址。 Previously I started piping the image from inside the response event but was causing an issue where images would be truncated without throwing any errors if the internet connection was interrupted ( See ). 以前,我从响应事件内部开始管道处理图像,但是导致了一个问题,即如果Internet连接中断,图像将被截断而不会引发任何错误( 请参阅参考资料 )。 This is my current code: 这是我当前的代码:

const fs = require('fs-extra');
var progress = require('request-progress');

var url = 'url to image';
var pathAndName = './Downloads/I want to call my image this'; // Does not include a file extension, just what I want the name of my image to be.
var req = request(url);
downloadImage(req, pathAndName).then(function(results) {
    console.dir(results);
}).catch(function(error) {
    console.error(error);
});

function downloadImage(req, pathAndName) {
    return new Promise((resolve, reject) => {
        if (!fs.existsSync(path.dirname(pathAndName))) fs.ensureDirSync(pathAndName);

        var response = null;
        var bytes = 0;
        var filename = '';
        progress(req, { delay: 0 }).on('progress', function (state) {
            // Report the download progress.
            console.log(state.speed);
        }).on('end', function () {
            // Check for errors before completing the download, the image might have been truncated even if a error was not triggered.
            if (response.statusCode == 200) {
                resolve({ bytes: bytes, filename: filename });
            } else {
                fs.unlinkSync(filename);
                reject({ 'name': 'StatusCodeError', 'message': response.statusCode });
            }
        }).on('response', function (resp) {
            response = resp;
            filename = pathAndName + '.' + mime.getExtension(response.headers['content-type']); // Here is too late to set the filename!
            bytes = response.headers['content-length'];
        }).on('error', function (error) {
            reject(error);
        }).pipe(fs.createWriteStream(filename)); // This needs to get the content-type returned by the response before piping!!!
    });
}

How can I download an image, determining its file extension from the response I get from the website and still properly handle download errors? 如何下载图像,并根据从网站获得的响应确定其文件扩展名,并且仍然可以正确处理下载错误?

You need to call two requests in a series. 您需要连续调用两个请求。 First only for header with 'HEAD' instead of 'GET' where you will get an extension (and file size). 首先仅针对带有“ HEAD”而不是“ GET”的标头,您将在其中获得扩展名(和文件大小)。 Second with full request and response for real download. 其次,具有完整的请求和响应,可以真正下载。 Here is example with callback but you can use it with a promise too. 这是带有回调的示例,但是您也可以将其与promise一起使用。

function callbackWithYourDownload(contentType){
   /*... your download code ...*/
}
var xhr = new XMLHttpRequest();
    xhr.open("HEAD", url, true);

xhr.onreadystatechange = function() {
    if (this.readyState == this.DONE) {
        var contentType = xhr.getResponseHeader("Content-Type");
        callbackWithYourDownload(contentType);
    }
};
xhr.send();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM