如何使用更新功能在CouchDB中上传附件

时间:2014-09-26 15:30:54

标签: function upload couchdb

我想知道如何使用更新功能在CouchDB中上传附件。

在这里,您将找到我的更新功能添加文档的示例:

function(doc, req){
if (!doc) {
    if (!req.form._id) {
        req.form._id = req.uuid;
    }
    req.form['|edited_by'] = req.userCtx.name
    req.form['|edited_on'] = new Date();

    return [req.form, JSON.stringify(req.form)];
}
else {
    return [null, "Use POST to add a document."]
}

}

删除文档的示例:

function(doc, req){
if (doc) {
    for (var i in req.form) {
        doc[i] = req.form[i];
    }

    doc['|edited_by'] = req.userCtx.name
    doc['|edited_on'] = new Date();
    doc._deleted = true;

    return [doc, JSON.stringify(doc)];      
}
else {
    return [null, "Document does not exist."]
}

}

感谢您的帮助,

1 个答案:

答案 0 :(得分:2)

可以通过修改文档的_attachments属性,使用更新功能向文档添加附件。这是一个更新功能的示例,它将向现有文档添加附件:

function (doc, req) {
  // skipping the create document case for simplicity
  if (!doc) {
    return [null, "update only"];
  }

  // ensure that the required form parameters are present
  if (!req.form || !req.form.name || !req.form.data) {
    return [null, "missing required post fields"];
  }

  // if there isn't an _attachments property on the doc already, create one
  if (!doc._attachments) {
    doc._attachments = {};
  }

  // create the attachment using the form data POSTed by the client
  doc._attachments[req.form.name] = {
    content_type: req.form.content_type || 'application/octet-stream',
    data: req.form.data
  };

  return [doc, "saved attachment"];
}

对于每个附件,您需要一个名称,内容类型和编码为base64的正文数据。上面的示例函数要求客户端以application/x-www-form-urlencoded格式发送带有至少两个参数的HTTP POST:namedata(如果提供,将使用content_type参数) :

name=logo.png&content_type=image/png&data=iVBORw0KGgoA...

测试更新功能:

  1. 查找一个小图片并对其进行base64编码:

    $ base64 logo.png | sed 's/+/%2b/g' > post.txt
    

    sed脚本对+个字符进行编码,因此无法转换为空格。

  2. 修改post.txt并将name=logo.png&content_type=image/png&data=添加到文档顶部。
  3. 使用Futon在CouchDB中创建一个新文档。
  4. 使用curl以post.txt文件作为正文调用更新函数,替换为刚刚创建的文档的ID。

    curl -X POST -d @post.txt http://127.0.0.1:5984/mydb/_design/myddoc/_update/upload/193ecff8618678f96d83770cea002910
    
  5. 这是在OSX上运行的CouchDB 1.6.1上测试的。


    更新:@janl非常友好地提供了有关此答案导致性能和扩展问题的原因的一些详细信息。通过上传处理​​程序上传附件有两个主要问题:

    1. 上传处理程序是用JavaScript编写的,因此CouchDB服务器可能需要fork()couchjs进程来处理上传。即使couchjs进程已在运行,服务器也必须通过stdin将整个HTTP请求流式传输到外部进程。对于大型附件,请求的传输可能需要大量时间和系统资源。对于像这样的更新函数的每个并发请求,CouchDB将不得不分叉一个新的couchjs进程。由于下面将要解释的原因,进程运行时间会相当长,因此您可以轻松地耗尽RAM,CPU或处理更多并发请求的能力。
    2. 在上传处理程序填充_attachments属性并流回CouchDB服务器(!)之后,服务器必须解析响应JSON,解码base64编码的附件主体,并将二进制主体写入磁盘。向文档添加附件的标准方法 - PUT /db/docid/attachmentname - 将二进制请求主体直接流式传输到磁盘,不需要两个处理步骤。
    3. 上述功能可以使用,但在高度可扩展的系统中使用它之前需要考虑一些非常重要的问题。