nodejs将图像从数据库传递到浏览器的最佳方法

时间:2019-02-14 21:14:35

标签: node.js oracle

我需要的最终结果是将多个图像从数据库发送到Web浏览器。

图像存储为斑点。

我知道我可以将它们从数据库流式传输到文件中,然后可以将URL提供给文件。

我还知道我可以将base64字符串传递给浏览器,以便它可以呈现图像。

我的问题是哪个选项最合适?还是最佳实践?请记住,如果使用流方法,则必须检查图像自上次显示以来是否已更改...如果图像已更改,则必须将其从数据库中重新传输。 / p>

我一直在为节点js使用oracldb,并且能够成功地将一个blob提取到一个文件中,但是我在传输多个文件时也遇到了麻烦。

这是两个问题的帖子:

哪个最佳:  1.发送Base64字符串-我有点喜欢这种方法,因为我不必担心流出文件并检查它是否已更改,因为它直接来自数据库。我担心的是浏览器/ nodejs是否可以处理?我知道这些字符串可能很大。我也可以一次发送多个图像。

  1. 将blob串流到文件中。

第二部分的问题是如何从下面的代码中获取多个blob,这是我在流式传输一个文件时的代码,我从github lobstream1.js找到了这个示例

https://raw.githubusercontent.com/oracle/node-oracledb/master/examples/lobstream1.js

关注代码:

// Stream a LOB to a file
var  dostream = function(lob, cb) {
  if (lob.type === oracledb.CLOB) {
    console.log('Writing a CLOB to ' + outFileName);
    lob.setEncoding('utf8');  // set the encoding so we get a 'string' not a 'buffer'
  } else {
    console.log('Writing a BLOB to ' + outFileName);
  }

  var errorHandled = false;

  lob.on(
    'error',
    function(err) {
      console.log("lob.on 'error' event");
      if (!errorHandled) {
        errorHandled = true;
        lob.close(function() {
          return cb(err);
        });
      }
    });
  lob.on(
    'end',
    function() {
      console.log("lob.on 'end' event");
    });
  lob.on(
    'close',
    function() {
      // console.log("lob.on 'close' event");
      if (!errorHandled) {
        return cb(null);
      }
    });

  var outStream = fs.createWriteStream(outFileName);
  outStream.on(
    'error',
    function(err) {
      console.log("outStream.on 'error' event");
      if (!errorHandled) {
        errorHandled = true;
        lob.close(function() {
          return cb(err);
        });
      }
    });

  // Switch into flowing mode and push the LOB to the file
  lob.pipe(outStream);
};

使用这种方法解决了将图像假脱机的问题,我确实对dostream做了一些更改。

for(var x = 0; x<result.rows.length;x++)
        {
          outputFileName = x + '.jpg';
          console.log(outputFileName);
          console.log(x);

          var lob = result.rows[x][0];
          dostream(lob,outputFileName);
//        cb(null,lob);
        }

谢谢您的帮助。

2 个答案:

答案 0 :(得分:0)

除非您进行平铺或base64内联编码之类的操作,否则每个图像都需要有自己的URL,因此,每次调用node-oracledb都只会返回一个图像。您可以通过写入磁盘来进行某种缓存,但这似乎是额外的IO-您将需要进行测试以衡量您自己的系统的性能和内存要求。关于访问node-oracledb中的多个映像,https://github.com/oracle/node-oracledb/issues/1041#issuecomment-459002641中有一些代码可能会有用。

答案 1 :(得分:0)

给出您在后续注释中提供的所有详细信息,包括平均图像大小,不同图像的数量,Node.js可用的内存,并发用户数以及“对图像进行更新非常关键”这一事实“,这是我的初衷...

对于第一个实施方案,请遵循KISS原则,并避免过度设计。禁用browser caching,并且不要在Node.js中缓存图像。而是依靠驱动程序和Oracle数据库为您完成繁重的工作。

对于存储图像的表,如果可能的话,请尝试使用BasicFile LOB上的SecureFile LOB(已知它们的性能更好)。另外,查看可用于两者的缓存选项(CACHE,CACHE READS和NOCACHE)。考虑根据您指定的工作量启用CACHE READS选项,但是请与DBA一起使用,以确保适当地调整缓冲区高速缓存的大小,以免影响其他缓存。

您可以依靠连接池的连接请求队列来帮助控制有多少人同时获取文件。实际上,您可能只想为此目的创建一个单独的池,以使获取LOB的人员不会阻止人们在应用程序中执行其他操作。例如,假设您通常有一个带有10个连接的连接池。您可以创建两个连接池,每个连接池具有5个连接(使用connection pool cache可以简化此过程)。然后,在获取lob的代码路径中,使用lob池,并将其他池用于其他所有内容。

鉴于此设置,我还建议您不要流式传输LOB。使用驱动程序在Node.js中缓冲LOB的功能将极大地简化代码,并且鉴于并发用户/文件提取的数量如此之少,您应该具有足够的内存。

此方案的最大问题是图像非常大,并且始终会从数据库通过Node.js流到浏览器。但是由于您将使用内部网络,所以这可能不是什么大问题。如果确实存在问题,则可以根据最有意义的方法开始在浏览器或Node.js中添加缓存。