{% include anchor.html edit="true" title="Save an attachment" hash="save_attachment" %} 

{% highlight js %}
db.putAttachment(docId, attachmentId, [rev], attachment, type, [callback]);
{% endhighlight %}

Attaches a binary object to a document.

This method will update an existing document to add the attachment, so it requires a `rev` if the document already exists. If the document doesn't already exist, then this method will create an empty document containing the attachment.

What's the point of attachments? If you're dealing with large binary data (such as PNGs), you may incur a performance or storage penalty if you naïvely include them as base64- or hex-encoded strings inside your documents. But if you insert the binary data as an attachment, then PouchDB will attempt to store it in [the most efficient way possible]({{ site.baseurl }}/faq.html#data_types).

For details, see the [CouchDB documentation on attachments](https://docs.couchdb.org/en/stable/api/document/attachments.html#put--db-docid-attname).

#### Example Usage:

{% include code/start.html id="attach1" type="callback" %}
{% highlight js %}
const attachment = new Blob(['Is there life on Mars?'], {type: 'text/plain'});
db.putAttachment('doc', 'att.txt', attachment, 'text/plain', function(err, res) {
  if (err) { return console.log(err); }
  // handle result
});
{% endhighlight %}
{% include code/end.html %}

{% include code/start.html id="attach1" type="async" %}
{% highlight js %}
try {
  const attachment = new Blob(['Is there life on Mars?'], {type: 'text/plain'});
  const result = await db.putAttachment('doc', 'att.txt', attachment, 'text/plain');
} catch (err) {
  console.log(err);
}
{% endhighlight %}
{% include code/end.html %}

{% include code/start.html id="attach1" type="promise" %}
{% highlight js %}
const attachment = new Blob(['Is there life on Mars?'], {type: 'text/plain'});
db.putAttachment('doc', 'att.txt', attachment, 'text/plain').then(function (result) {
  // handle result
}).catch(function (err) {
  console.log(err);
});
{% endhighlight %}
{% include code/end.html %}


#### Example Response:
{% highlight js %}
{
  "ok": true,
  "id": "doc",
  "rev": "2-068E73F5B44FEC987B51354DFC772891"
}
{% endhighlight %}

Within Node, you must use a `Buffer` instead of a `Blob`:

{% highlight js %}
const attachment = new Buffer('Is there life on Mars?');
{% endhighlight %}

For details, see the [Mozilla docs on `Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or the [Node docs on `Buffer`](http://nodejs.org/api/buffer.html).

If you need a shim for older browsers that don't support the `Blob` constructor, or you want some convenience methods for Blobs, you can use [blob-util](https://github.com/nolanlawson/blob-util).

#### Save a base64 attachment

If you supply a string instead of a `Blob`/`Buffer`, then it will be assumed to be a base64-encoded string, and will be processed accordingly:

{% include code/start.html id="attach3" type="callback" %}
{% highlight js %}
const attachment =
        "TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKTWFrZS" +
        "BvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA==";
db.putAttachment('doc', 'att.txt', attachment, 'text/plain', function(err, res) {
  if (err) { return console.log(err); }
  // handle result
});
{% endhighlight %}
{% include code/end.html %}

{% include code/start.html id="attach3" type="async" %}
{% highlight js %}
try {
  const attachment =
    "TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKTWFrZS" +
    "BvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA==";
  const result = await db.putAttachment('doc', 'att.txt', attachment, 'text/plain');
} catch (err) {
  console.log(err);
}
{% endhighlight %}
{% include code/end.html %}

{% include code/start.html id="attach3" type="promise" %}
{% highlight js %}
const attachment =
        "TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKTWFrZS" +
        "BvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA==";
db.putAttachment('doc', 'att.txt', attachment, 'text/plain').then(function (result) {
  // handle result
}).catch(function (err) {
  console.log(err);
});
{% endhighlight %}
{% include code/end.html %}


#### Save an inline attachment

You can also inline attachments inside the document. The attachment data may be supplied as a base64-encoded string with the `content_type`:

{% include code/start.html id="attach2" type="callback" %}
{% highlight js %}
const doc = {
  "_id": "doc",
  "title": "Legendary Hearts",
  "_attachments": {
    "att.txt": {
      "content_type": "text/plain",
      "data": "TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKTWFrZS" +
              "BvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA=="
    }
  }
};
db.put(doc, function (err, result) {
  if (err) { return console.log(err); }
  // handle result
});
{% endhighlight %}
{% include code/end.html %}

{% include code/start.html id="attach2" type="async" %}
{% highlight js %}
try {
  const doc = {
    "_id": "doc",
    "title": "Legendary Hearts",
    "_attachments": {
      "att.txt": {
        "content_type": "text/plain",
        "data": "TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKTWFrZS" +
          "BvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA=="
      }
    }
  };
  const result = await db.put(doc);
} catch (err) {
  console.log(err);
}
{% endhighlight %}
{% include code/end.html %}

{% include code/start.html id="attach2" type="promise" %}
{% highlight js %}
const doc = {
  "_id": "doc",
  "title": "Legendary Hearts",
  "_attachments": {
    "att.txt": {
      "content_type": "text/plain",
      "data": "TGVnZW5kYXJ5IGhlYXJ0cywgdGVhciB1cyBhbGwgYXBhcnQKTWFrZS" +
              "BvdXIgZW1vdGlvbnMgYmxlZWQsIGNyeWluZyBvdXQgaW4gbmVlZA=="
    }
  }
};
db.put(doc).then(function (result) {
  // handle result
}).catch(function (err) {
  console.log(err);
});
{% endhighlight %}
{% include code/end.html %}

#### Save an inline Blob/Buffer attachment

You can also inline `Blob`s/`Buffer`s:

{% include code/start.html id="attach4" type="callback" %}
{% highlight js %}
const doc = {
  "_id": "doc",
  "title": "Legendary Hearts",
  "_attachments": {
    "att.txt": {
      "content_type": "text/plain",
      "data": new Blob(['Is there life on Mars?'], {type: 'text/plain'})
    }
  }
};
db.put(doc, function (err, result) {
  if (err) { return console.log(err); }
  // handle result
});
{% endhighlight %}
{% include code/end.html %}

{% include code/start.html id="attach4" type="async" %}
{% highlight js %}
try {
  const doc = {
    "_id": "doc",
    "title": "Legendary Hearts",
    "_attachments": {
      "att.txt": {
        "content_type": "text/plain",
        "data": new Blob(['Is there life on Mars?'], {type: 'text/plain'})
      }
    }
  };
  const result = await db.put(doc);
} catch (err) {
  console.log(err);
}
{% endhighlight %}
{% include code/end.html %}

{% include code/start.html id="attach4" type="promise" %}
{% highlight js %}
const doc = {
  "_id": "doc",
  "title": "Legendary Hearts",
  "_attachments": {
    "att.txt": {
      "content_type": "text/plain",
      "data": new Blob(['Is there life on Mars?'], {type: 'text/plain'})
    }
  }
};
db.put(doc).then(function (result) {
  // handle result
}).catch(function (err) {
  console.log(err);
});
{% endhighlight %}
{% include code/end.html %}

#### Save many attachments at once

The inline approach allows you to save multiple attachments to the same document in a single shot:

{% include code/start.html id="attach5" type="callback" %}
{% highlight js %}
const doc = {
  "_id": "doc",
  "title": "Legendary Hearts",
  "_attachments": {
    "att.txt": {
      "content_type": "text/plain",
      "data": new Blob(
        ["And she's hooked to the silver screen"],
        {type: 'text/plain'})
    },
    "att2.txt": {
      "content_type": "text/plain",
      "data": new Blob(
        ["But the film is a saddening bore"],
        {type: 'text/plain'})
    },
    "att3.txt": {
      "content_type": "text/plain",
      "data": new Blob(
        ["For she's lived it ten times or more"],
        {type: 'text/plain'})
    }
  }
};
db.put(doc, function (err, result) {
  if (err) { return console.log(err); }
  // handle result
});
{% endhighlight %}
{% include code/end.html %}

{% include code/start.html id="attach5" type="async" %}
{% highlight js %}
try {
  const doc = {
    "_id": "doc",
    "title": "Legendary Hearts",
    "_attachments": {
      "att.txt": {
        "content_type": "text/plain",
        "data": new Blob(
          ["And she's hooked to the silver screen"],
          {type: 'text/plain'})
      },
      "att2.txt": {
        "content_type": "text/plain",
        "data": new Blob(
          ["But the film is a saddening bore"],
          {type: 'text/plain'})
      },
      "att3.txt": {
        "content_type": "text/plain",
        "data": new Blob(
          ["For she's lived it ten times or more"],
          {type: 'text/plain'})
      }
    }
  };
  const result = await db.put(doc);
} catch (err) {
  console.log(err);
}
{% endhighlight %}
{% include code/end.html %}

{% include code/start.html id="attach5" type="promise" %}
{% highlight js %}
const doc = {
  "_id": "doc",
  "title": "Legendary Hearts",
  "_attachments": {
    "att.txt": {
      "content_type": "text/plain",
      "data": new Blob(
        ["And she's hooked to the silver screen"], 
        {type: 'text/plain'})
    },
    "att2.txt": {
      "content_type": "text/plain",
      "data": new Blob(
        ["But the film is a saddening bore"], 
        {type: 'text/plain'})
    },
    "att3.txt": {
      "content_type": "text/plain",
      "data": new Blob(
        ["For she's lived it ten times or more"], 
        {type: 'text/plain'})
    }
  }
};
db.put(doc).then(function (result) {
  // handle result
}).catch(function (err) {
  console.log(err);
});
{% endhighlight %}
{% include code/end.html %}

See [Inline Attachments](https://docs.couchdb.org/en/stable/api/document/common.html?highlight=inline%20attachment#creating-multiple-attachments)
on the CouchDB wiki for details.


