节点REST API图像渲染问题

Node REST API Image rendering issue

本文关键字:问题 图像 REST API 节点      更新时间:2023-09-26

我在网页上显示一个简单图像时遇到问题。我有一个用于API的节点后端和一个用于视图页面的节点web服务器。代码运行得很好,但我需要在两者之间添加一种网关(将来将处理身份验证),它破坏了代码。

我使用express和gridfs来存储和检索mongo文件。

这是代码

HTML/Angular页面

<img id="image" ng-src="http:localhost:3000/api/files/images/{{data.image}}" alt="" />

网关(节点)

var request = require('request');
//settings - retrive the url of the api backend micro-service
var url = require('./configApiGw').url_service_api_contents; 
//api to retrive a file stored in mongo using gridfs
app.get('/api/files/images/:id', function(req, res, next){
    var uri = url+'/api/files/images/:'+req.params.id;
    request({
        uri: uri,
        method: "GET",
        timeout: 100000,
        followRedirect: true,
        maxRedirects: 10
    }, function(error, response, body) {    
            res.send(response.body);
    }); 
});

后端API

app.get('/api/files/images/:id', function(req, res, next){
    //call function to read the file using gridfs. call back function
    readFile(req, res, function(file){
        console.log('success');
    });
});
function readFile(req,res,callback){
  var fileId = req.params.id;
  //delete the ':' that is added by the gateway
  if(fileId.charAt(0) === ':'){
    fileId = fileId.slice(1);
  }
  // streaming from gridfs
  var rstream = gfs.createReadStream({filename: fileId});
  var bufs = [];
  rstream.on('data', function (chunk) {
    bufs.push(chunk);
  });
  // done reading the file 
  rstream.on('end', function () { 
    var fbuf = Buffer.concat(bufs);
    var file = (fbuf.toString('base64'));
    callback(file);
  });
  //error handling, e.g. file does not exist
  rstream.on('error', function (err) {
    console.log('An error occurred!', err);
    console.log(err);
    res.send(500,err);
  }); 
  rstream.pipe(res);
}

图像没有显示,但我从API后端和网关都得到了200 OK的响应。当我在浏览器上查看图像详细信息时,我会看到以下数据:-地点:http://localhost:3000/api/files/images/file.jpeg-类型:text.html-大小:未知(未缓存)

我做错了什么?非常感谢。

使用Alexandr输入进行编辑

网关(节点)V2

var request = require('request');
//settings - retrive the url of the api backend micro-service
var url = require('./configApiGw').url_service_api_contents; 
app.get('/api/files/images/:id', function(req, res, next){
var uri = url+'/api/files/images/:'+req.params.id;
request({
    uri: uri,
    method: "GET",
    timeout: 100000,
    followRedirect: true,
    maxRedirects: 10
}, function(error, response, body) { 
        res.set('Content-Type', response.headers['content-type']);   
        res.send(response.body);
   }); 
});

后端API V2

//api to retrive a file stored in mongo using gridfs
app.get('/api/files/images/:id', function(req, res, next){
    //call function to read the file using gridfs. call back function
    db.readFile(req, res, function(file){
      //res.send(file);
      console.log("success");
  });
});
readFile = function(req,res,callback){
  var fileId = req.params.id;
  //delete the ':' that is added by the gateway
  if(fileId.charAt(0) === ':'){
    fileId = fileId.slice(1);
  }
  //setHeaders content type for the file
  setHeaders(fileId, function(contentType){
    res.writeHead('200',{'Content-Type':contentType});
    // streaming from gridfs
    var rstream = gfs.createReadStream({filename: fileId});
    var bufs = [];
    rstream.on('data', function (chunk) {
      bufs.push(chunk);
    });
    // done reading the file 
    rstream.on('end', function () { 
      var fbuf = Buffer.concat(bufs);
      var file = (fbuf.toString('binary'));
      callback(file);
    });
    //error handling, e.g. file does not exist
    rstream.on('error', function (err) {
      console.log('An error occurred!', err);
     console.log(err);
      res.send(500,err);
    }); 
    rstream.pipe(res);
  });
};
function setHeaders(fileId, callback){
  var ext = path.extname(fileId);
  var contentType = 'text/html';
    if (ext === '.gif') {
       contentType = 'image/gif';
    }
    if (ext === '.jpeg') {
       contentType = 'image/jepg';
    }
    if (ext === '.png') {
       contentType = 'image/png';
    }
    if (ext === '.jpg') {
       contentType = 'image/jpg';
    }
  callback(contentType);
}

结果仍然不好:图像没有显示。但现在,内容类型设置正确。

在这里添加标题(邮递员):

Access-Control-Allow-Headers → Origin, X-Requested-With, Content-Type, Accept
Access-Control-Allow-Origin → *
Connection → keep-alive
Content-Length → 82360
Content-Type → image/jepg; charset=utf-8
Date → Fri, 20 Nov 2015 10:15:55 GMT
ETag → W/"141b8-Ox5qDdvc3kZTunf0uqMVQg"
X-Powered-By → Express

更新

尝试在请求对象中将encoding属性设置为null

app.get('/api/files/images/:id', function(req, res, next){
var uri = url+'/api/files/images/:'+req.params.id;
request({
    uri: uri,
    method: "GET",
    timeout: 100000,
    followRedirect: true,
    encoding: null, 
    maxRedirects: 10
}, function(error, response, body) { 
        res.set('Content-Type', response.headers['content-type']);   
        res.send(response.body);
   }); 
});

此外,为您的响应设置图像内容类型标题:

app.get('/api/files/images/:id', function(req, res, next){
    //call function to read the file using gridfs. call back function
    readFile(req, res, function(file){
        res.set('Content-Type', 'image/jpeg'); //it can different, depends on the image
        res.send(file);
    });
});

网关:

app.get('/api/files/images/:id', function(req, res, next){
var uri = url+'/api/files/images/:'+req.params.id;
request({
    uri: uri,
    method: "GET",
    timeout: 100000,
    followRedirect: true,
    maxRedirects: 10
}, function(error, response, body) { 
        res.set('Content-Type', response.headers['content-type']);   
        res.send(response.body);
   }); 
});

是的,我已经为页面的所有其他组件使用了控制器,但我直接从html页面调用API来检索图像。你说得对,我可以改变。网关在这里也是因为我有多个API组件(微服务架构),所以网关是为web客户端抽象所有这些不同组件的好方法。我更愿意保留网关以遵循微服务架构模式。