Remote Attachment Content Type
Remote attachments of any size can be sent using the RemoteAttachmentCodec
and a storage provider.
Install the package
- JavaScript
npm i @xmtp/content-type-remote-attachment
Import and register
- JavaScript
// Import the codecs we're going to use
import {
AttachmentCodec,
RemoteAttachmentCodec,
} from "@xmtp/content-type-remote-attachment";
// Create the XMTP client
const xmtp = await Client.create(signer, { env: "dev" });
// Register the codecs. AttachmentCodec is for local attachments (<1MB)
xmtp.registerCodec(new AttachmentCodec());
//RemoteAttachmentCodec is for remote attachments (>1MB) using thirdweb storage
xmtp.registerCodec(new RemoteAttachmentCodec());
Create an attachment object
- JavaScript
// Local file details
const attachment = {
filename: filename,
mimeType: extname,
data: new Uint8Array(data),
};
Encrypt the attachment
Use the RemoteAttachmentCodec.encodeEncrypted
to encrypt the attachment:
- JavaScript
const encryptedEncoded = await RemoteAttachmentCodec.encodeEncrypted(
attachment,
new AttachmentCodec(),
);
Upload the encrypted attachment
Upload the encrypted attachment anywhere where it will be accessible via an HTTPS GET request. For example, you can use web3.storage:
- Web3 Storage
- Thirdweb
const { Web3Storage } = require("web3.storage");
class Upload {
constructor(name, data) {
this.name = name;
this.data = data;
}
stream() {
const self = this;
return new ReadableStream({
start(controller) {
controller.enqueue(Buffer.from(self.data));
controller.close();
},
});
}
}
const upload = new Upload("uploadIdOfYourChoice", encryptedEncoded.payload);
const web3Storage = new Web3Storage({
token: "YOURTOKENHERE",
});
const cid = await web3Storage.put([upload]);
const url = `https://${cid}.ipfs.w3s.link/uploadIdOfYourChoice`;
import { useStorageUpload } from "@thirdweb-dev/react";
const { mutateAsync: upload } = useStorageUpload();
const uploadUrl = await upload({
//encryptedEncoded.payload.buffer is a Uint8Array
//We need to convert it to a File to upload it to the IPFS network
data: [new File([encryptedEncoded.payload.buffer], file.name)], // Convert Uint8Array back to File
options: { uploadWithGatewayUrl: true, uploadWithoutDirectory: true },
});
const url = uploadUrl[0];
Create a remote attachment
Now that you have a url
, you can create a RemoteAttachment
.
- JavaScript
const remoteAttachment = {
url: url,
contentDigest: encryptedEncoded.digest,
salt: encryptedEncoded.salt,
nonce: encryptedEncoded.nonce,
secret: encryptedEncoded.secret,
scheme: "https://",
filename: attachment.filename,
contentLength: attachment.data.byteLength,
};
Send a remote attachment
Now that you have a remote attachment, you can send it:
- JavaScript
await conversation.send(remoteAttachment, {
contentType: ContentTypeRemoteAttachment,
});
Download, decrypt, and decode the attachment
Now that you can receive a remote attachment, you need a way to receive a remote attachment. For example:
- JavaScript
if (message.contentType.sameAs(RemoteAttachmentContentType)) {
const attachment = await RemoteAttachmentCodec.load(message.content, client);
}
- You now have the original attachment:
attachment.filename // => "screenshot.png"
attachment.mimeType // => "image/png",
attachment.data // => [the PNG data]
Create a preview attachment object
Once you have the attachment object created, you can also create a preview for what to show in a message input before sending:
- JavaScript
URL.createObjectURL(
new Blob([Buffer.from(attachment.data)], {
type: attachment.mimeType,
}),
),