Copy / Move / Rename Attachments
-
You can copy, move, or rename attachments using the Session's methods.
These actions are executed on the server when callingSaveChanges(). -
In this article:
Copy attachment to another document
-
Copying LOCAL attachments:
The target document's metadata is updated to reference the same attachment.
The binary content is Not duplicated, it remains stored once in the database,
even if the copied attachment has a different name in the target document. -
Copying REMOTE attachments:
The target document's metadata is updated to reference the existing attachment in remote storage.
The attachment is Not re-uploaded or duplicated in the remote destination,
even if the copied attachment has a different name in the target document.
Copy attachments - via the session
-
Use the session's
Advanced.Attachments.Copymethod to copy an attachment from one document to another. You can assign any name to the copied attachment in the target document, it doesn't have to match the source name. -
An exception is thrown in any of the following cases:
- The source document does not exist.
- The destination document does not exist.
- The specified attachment is not found in the source document.
- An attachment with the same name already exists in the target document.
- Copy_attachment
- Copy_attachment_async
using (var session = store.OpenSession())
{
// Load source document
var employee1 = session.Load<Employee>("employees/1");
// Load target document
var employee2 = session.Load<Employee>("employees/2");
// Copy the attachment from employee1 to employee2
session.Advanced.Attachments.Copy(employee1, "notes.txt", employee2, "notes-copy.txt");
// Alternatively, use document IDs:
// session.Advanced.Attachments.Copy(
// "employees/1", "notes.txt", "employees/2", "notes-copy.txt");
// The attachment will be copied only when 'SaveChanges' is called
session.SaveChanges();
}
using (var asyncSession = store.OpenAsyncSession())
{
// Load source document
var employee1 = await asyncSession.LoadAsync<Employee>("employees/1");
// Load target document
var employee2 = await asyncSession.LoadAsync<Employee>("employees/2");
// Copy the attachment from employee1 to employee2
asyncSession.Advanced.Attachments.Copy(employee1, "notes.txt", employee2, "notes-copy.txt");
// Alternatively, use document IDs:
// asyncSession.Advanced.Attachments.Copy(
// "employees/1", "notes.txt", "employees/2", "notes-copy.txt");
// The attachment will be copied only when 'SaveChangesAsync' is called
await asyncSession.SaveChangesAsync();
}
Copy attachments - via patching
-
Use
attachments(targetDocument, targetAttachmentName).copyFrom(sourceDocId, sourceAttachmentName)to copy an attachment between documents within a patch script. The method copies the attachment from the source document and assigns it to the target document under the specified name. -
In both single-document patches and patch-by-query operations, the copy is performed entirely server-side,
without requiring the attachment to be downloaded and re-uploaded through the client. -
An exception is thrown in the following case:
- An attachment with the specified name already exists on the target document.
-
No exception is thrown in the following cases:
- The source document does not exist.
- The destination document does not exist.
- The specified attachment is not found in the source document.
- Copy_attachment_via_patch
- Copy_attachment_via_patch_async
- Copy_attachment_via_patch_by_query
// Define the patch request
var patchRequest = new PatchRequest
{
// Copy attachment 'photo.jpg' from 'employees/1' to the patched document
// and name it 'photo-copy.jpg' in the target document
Script = "attachments(this, args.targetName).copyFrom(args.sourceDocId, args.sourceName);",
Values =
{
{ "sourceDocId", "employees/1" },
{ "sourceName", "photo.jpg" },
{ "targetName", "photo-copy.jpg" }
}
};
// Execute the patch operation on the target document
store.Operations.Send(new PatchOperation("employees/2", null, patchRequest));
// Define the patch request
var patchRequest = new PatchRequest
{
// Copy attachment 'photo.jpg' from 'employees/1' to the patched document
// and name it 'photo-copy.jpg' in the target document
Script = "attachments(this, args.targetName).copyFrom(args.sourceDocId, args.sourceName);",
Values =
{
{ "sourceDocId", "employees/1" },
{ "sourceName", "photo.jpg" },
{ "targetName", "photo-copy.jpg" }
}
};
// Execute the patch operation asynchronously on the target document
await store.Operations.SendAsync(new PatchOperation("employees/2", null, patchRequest));
// Copy an attachment to ALL documents in a collection using a patch-by-query operation
var op = store.Operations.Send(new PatchByQueryOperation(new IndexQuery
{
Query = @"
from Employees as e
update {
attachments(e, 'photo-copy.jpg').copyFrom('employees/1', 'photo.jpg');
}"
}));
op.WaitForCompletion();
Move attachment to another document
-
Use the session's
Advanced.Attachments.Movemethod to move an attachment from one document to another. You can assign a new name to the moved attachment in the target document, it doesn't have to match the source name. -
Whether the attachment is stored locally or remotely, the reference is removed from the source document,
and the target document’s metadata is updated to reference it. -
An exception is thrown in any of the following cases:
- The source document does not exist.
- The destination document does not exist.
- The specified attachment is not found in the source document.
- An attachment with the same name already exists in the target document.
- Move_attachment
- Move_attachment_async
using (var session = store.OpenSession())
{
// Load source document
var employee1 = session.Load<Employee>("employees/1");
// Load target document
var employee2 = session.Load<Employee>("employees/2");
// Move the attachment from employee1 to employee2
session.Advanced.Attachments.Move(employee1, "notes.txt", employee2, "notes.txt");
// Alternatively, use document IDs:
// session.Advanced.Attachments.Move(
// "employees/1", "notes.txt", "employees/2", "notes.txt");
// The attachment will be moved only when 'SaveChanges' is called
session.SaveChanges();
}
using (var asyncSession = store.OpenAsyncSession())
{
// Load source document
var employee1 = await asyncSession.LoadAsync<Employee>("employees/1");
// Load target document
var employee2 = await asyncSession.LoadAsync<Employee>("employees/2");
// Move the attachment from employee1 to employee2
asyncSession.Advanced.Attachments.Move(employee1, "notes.txt", employee2, "notes.txt");
// Alternatively, use document IDs:
// asyncSession.Advanced.Attachments.Move(
// "employees/1", "notes.txt", "employees/2", "notes.txt");
// The attachment will be moved only when 'SaveChangesAsync' is called
await asyncSession.SaveChangesAsync();
}
Rename attachment
-
Use the session's
Advanced.Attachments.Renamemethod to rename an existing attachment in a document.
You can assign any new name - the attachment content remains unchanged. -
Renaming an attachment only affects the document’s metadata.
The actual content is stored once using the hash of its binary data,
so neither local nor remote storage is affected by the name change. -
An exception is thrown in any of the following cases:
- The document does not exist.
- The specified attachment is not found in the document.
- An attachment with the new name already exists in the document.
- Rename_attachment
- Rename_attachment_async
using (var session = store.OpenSession())
{
// Load a document
var employee1 = session.Load<Employee>("employees/1");
// Rename the attachment
session.Advanced.Attachments.Rename(
employee1, name: "notes.txt", newName: "notes-new-name.txt");
// Alternatively, use document ID:
// session.Advanced.Attachments.Rename(
// "employees/1", name: "notes.txt", newName: "notes-new-name.txt");
// The attachment will be renamed only when 'SaveChanges' is called
session.SaveChanges();
}
using (var asyncSession = store.OpenAsyncSession())
{
// Load a document
var employee1 = await asyncSession.LoadAsync<Employee>("employees/1");
// Rename the attachment
asyncSession.Advanced.Attachments.Rename(
employee1, name: "notes.txt", newName: "notes-new-name.txt");
// Alternatively, use document ID:
// asyncSession.Advanced.Attachments.Rename(
// "employees/1", name: "notes.txt", newName: "notes-new-name.txt");
// The attachment will be renamed only when 'SaveChangesAsync' is called
await asyncSession.SaveChangesAsync();
}
Syntax
Copy attachment
// Available overloads:
// ====================
void Copy(
object sourceEntity, string sourceName, object destinationEntity, string destinationName);
void Copy(
string sourceDocumentId, string sourceName, string destinationDocumentId, string destinationName);
Move attachment
// Available overloads:
// ====================
void Move(
object sourceEntity, string sourceName, object destinationEntity, string destinationName);
void Move(
string sourceDocumentId, string sourceName, string destinationDocumentId, string destinationName);
| Parameter | Type | Description |
|---|---|---|
| sourceEntity | object | The source document entity that holds the attachment. |
| sourceDocumentId | string | The source document ID that holds the attachment. |
| sourceName | string | The attachment name in the source document. |
| destinationEntity | object | The target document entity. |
| destinationDocumentId | string | The target document ID. |
| destinationName | string | The name to assign to the attachment in the target document. |
Rename attachment
void Rename(object entity, string name, string newName);
void Rename(string documentId, string name, string newName);
| Parameter | Type | Description |
|---|---|---|
| entity | object | The document entity that holds the attachment. |
| documentId | string | The document ID that holds the attachment. |
| name | string | The current name of the attachment. |
| newName | string | The new name to assign to the attachment. |
Copy attachment via patch script
attachments(document, attachmentName).copyFrom(sourceDocId, sourceName)
| Parameter | Type | Description |
|---|---|---|
| document | object | The target document entity (use this for the current document being patched). |
| attachmentName | string | The name to assign to the copied attachment in the target document. |
| sourceDocId | string | The ID of the source document that holds the attachment to copy. |
| sourceName | string | The name of the attachment to copy from the source document. |
| Return value | Description |
|---|---|
true | The attachment was copied successfully. |
false | The source document, the destination document, or the source attachment was not found. No exception is thrown. |
See JavaScript engine for the full list of JavaScript methods available in RavenDB.