diff --git a/src/MatrixClient.ts b/src/MatrixClient.ts
index f9ca9e44..73c40384 100644
--- a/src/MatrixClient.ts
+++ b/src/MatrixClient.ts
@@ -1609,6 +1609,29 @@ export class MatrixClient extends EventEmitter {
.then(response => response["content_uri"]);
}
+ /**
+ * Download Authenticated content from the homeserver's media repository. Note that this will not automatically
+ * decrypt media as it cannot determine if the media is encrypted.
+ * @param {string} mxcUrl The MXC URI for the content.
+ * @param {number} timeoutMs The maximum number of milliseconds that the client is willing to wait to start receiving data,
+ * in the case that the content has not yet been uploaded. The default value is 20000 (20 seconds).
+ * @returns {Promise<{data: Buffer, contentType: string}>} Resolves to the downloaded content.
+ */
+ public async downloadAuthenticatedContent(mxcUrl: string, timeoutMs = 20000): Promise<{ data: Buffer, contentType: string }> {
+ if (!mxcUrl.toLowerCase().startsWith("mxc://")) {
+ throw Error("'mxcUrl' does not begin with mxc://");
+ }
+ const urlParts = mxcUrl.substr("mxc://".length).split("/");
+ const domain = encodeURIComponent(urlParts[0]);
+ const mediaId = encodeURIComponent(urlParts[1].split("/")[0]);
+ const path = `/_matrix/client/v1/media/download/${domain}/${mediaId}`;
+ const res = await this.doRequest("GET", path, { timeout_ms: timeoutMs }, null, null, true, null, true);
+ return {
+ data: res.body,
+ contentType: res.headers["content-type"],
+ };
+ }
+
/**
* Download content from the homeserver's media repository. Note that this will not automatically decrypt
* media as it cannot determine if the media is encrypted.
diff --git a/test/MatrixClientTest.ts b/test/MatrixClientTest.ts
index 6abdf93e..d7d90484 100644
--- a/test/MatrixClientTest.ts
+++ b/test/MatrixClientTest.ts
@@ -5727,6 +5727,35 @@ describe('MatrixClient', () => {
});
});
+ describe('downloadAuthenticatedContent', () => {
+ it('should call the right endpoint', async () => {
+ const { client, http } = createTestClient();
+ const urlPart = "example.org/testing";
+ const mxcUrl = "mxc://" + urlPart;
+ // const fileContents = Buffer.from("12345");
+
+ // noinspection TypeScriptValidateJSTypes
+ http.when("GET", "/_matrix/client/v1/media/download/").respond(200, (path, _, req) => {
+ expect(path).toContain("/_matrix/client/v1/media/download/" + urlPart);
+ expect((req as any).opts.encoding).toEqual(null);
+ // TODO: Honestly, I have no idea how to coerce the mock library to return headers or buffers,
+ // so this is left as a fun activity.
+ // return {
+ // body: fileContents,
+ // headers: {
+ // "content-type": "test/test",
+ // },
+ // };
+ return {};
+ });
+
+ // Due to the above problem, the output of this won't be correct, so we cannot verify it.
+ const [res] = await Promise.all([client.downloadAuthenticatedContent(mxcUrl), http.flushAllExpected()]);
+ expect(Object.keys(res)).toContain("data");
+ expect(Object.keys(res)).toContain("contentType");
+ });
+ });
+
describe('downloadContent', () => {
it('should call the right endpoint', async () => {
const { client, http } = createTestClient();