3

我有一个 Node.js 服务器,它从数据库(mongodb)中的图像(640x640)动态生成并提供小(200x200)缩略图。我正在使用node-imagemagick模块进行缩略图。

我的代码大约 95% 的时间都在工作;客户端 (iOS) 上大约有 20 个(或更少)缩略图图像损坏,它报告:

JPEG Corrupt JPEG 数据:数据段过早结束

对于损坏的图像,客户端显示图像的前 50% - 75%,其余部分被截断。

该行为是不确定的,并且损坏的特定图像会根据每个请求进行更改。

我正在使用以下代码调整图像大小并输出缩略图:

im.resize({
  srcData: image.imageData.buffer,
  width: opt_width,
}, function(err, stdout) {
  var responseHeaders = {};
  responseHeaders['content-type'] = 'image/jpeg';
  responseHeaders['content-length'] = stdout.length;
  debug('Writing ', stdout.length, ' bytes.');
  response.writeHead(200, responseHeaders);
  response.write(stdout, 'binary');
  response.end();
});

这里有什么问题?

笔记:

  1. content-length问题不在于标题不正确。当我省略标题时,结果是一样的。
  2. 当我不调整图像大小时,全尺寸图像似乎总是很好。
  3. 在研究这个问题时,我发现了这个问题和这个StackOverflow 问题,它们都通过增加缓冲区大小来解决问题。在我的情况下,图像非常小,所以这似乎不太可能负责。
  4. 我最初分配stdout给 anew Buffer(stdout, 'binary')并写下那个。删除它('binary'将被弃用)没有任何区别。
4

1 回答 1

1

问题似乎是由于node-imagemagick (0.1.2) 的版本稍旧;升级到 0.1.3 是解决方案。

如果这对任何人都有帮助,这里是我用来让 Node.js 排队并一次处理一个客户端请求的代码。

// Set up your server like normal.
http.createServer(handleRequest);
// ...

var requestQueue = [];
var isHandlingRequest = false;  // Prevent new requests from being handled.

// If you have any endpoints that don't always call response.end(), add them here.
var urlsToHandleConcurrently = {
  '/someCometStyleThingy': true
};

function handleRequest(req, res) {
  if (req.url in urlsToHandleConcurrently) {
    handleQueuedRequest(req, res);
    return;
  }
  requestQueue.push([req, res]);  // Enqueue new requests.
  processRequestQueue();          // Check if a request in the queue can be handled.
}

function processRequestQueue() {
  // Continue if no requests are being processed and the queue is not empty.
  if (isHandlingRequest) return;
  if (requestQueue.length == 0) return;

  var op = requestQueue.shift();

  var req = op[0], res = op[1];

  // Wrap .end() on the http.ServerRequest instance to
  // unblock and process the next queued item.
  res.oldEnd = res.end;
  res.end = function(data) {
    res.oldEnd(data);
    isHandlingRequest = false;
    processRequestQueue();
  };

  // Start handling the request, while blocking the queue until res.end() is called.
  isHandlingRequest = true;
  handleQueuedRequest(req, res);
}

function handleQueuedRequest(req, res) {
  // Your regular request handling code here...
}
于 2012-11-02T07:07:42.920 回答