Fix downloaded attachments not being decrypted (#30433)

* Fix downloaded attachments not being decrypted

Fixes https://github.com/element-hq/element-web/issues/30339

* Import order
This commit is contained in:
David Baker 2025-07-30 13:30:18 +01:00 committed by GitHub
parent 452996eacf
commit 1e15a322a5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 7 deletions

View File

@ -59,15 +59,19 @@ export function useDownloadMedia(url: string, fileName?: string, mxEvent?: Matri
return downloadBlob(blobRef.current);
}
const res = await fetch(url);
if (!res.ok) {
throw parseErrorResponse(res, await res.text());
// We must download via the mediaEventHelper if given as the file may need decryption.
if (mediaEventHelper) {
blobRef.current = await mediaEventHelper.sourceBlob.value;
} else {
const res = await fetch(url);
if (!res.ok) {
throw parseErrorResponse(res, await res.text());
}
blobRef.current = await res.blob();
}
const blob = await res.blob();
blobRef.current = blob;
await downloadBlob(blob);
await downloadBlob(blobRef.current);
} catch (e) {
showError(e);
}

View File

@ -10,11 +10,13 @@ import React from "react";
import { mocked } from "jest-mock";
import { render, fireEvent, waitFor } from "jest-matrix-react";
import fetchMock from "fetch-mock-jest";
import { MatrixEvent } from "matrix-js-sdk/src/matrix";
import ImageView from "../../../../../src/components/views/elements/ImageView";
import { FileDownloader } from "../../../../../src/utils/FileDownloader";
import Modal from "../../../../../src/Modal";
import ErrorDialog from "../../../../../src/components/views/dialogs/ErrorDialog";
import { stubClient } from "../../../../test-utils";
jest.mock("../../../../../src/utils/FileDownloader");
@ -44,6 +46,39 @@ describe("<ImageView />", () => {
expect(fetchMock).toHaveFetched("https://example.com/image.png");
});
it("should use event as download source if given", async () => {
stubClient();
const event = new MatrixEvent({
event_id: "$eventId",
type: "m.image",
content: {
body: "fromEvent.png",
url: "mxc://test.dummy/fromEvent.png",
file_name: "filename.png",
},
origin_server_ts: new Date(2000, 0, 1, 0, 0, 0, 0).getTime(),
});
fetchMock.get("http://this.is.a.url/test.dummy/fromEvent.png", "TESTFILE");
const { getByRole } = render(
<ImageView
src="https://test.dummy/fromSrc.png"
name="fromName.png"
onFinished={jest.fn()}
mxEvent={event}
/>,
);
fireEvent.click(getByRole("button", { name: "Download" }));
await waitFor(() =>
expect(mocked(FileDownloader).mock.instances[0].download).toHaveBeenCalledWith({
blob: expect.anything(),
name: "fromEvent.png",
}),
);
expect(fetchMock).toHaveFetched("http://this.is.a.url/test.dummy/fromEvent.png");
});
it("should start download on Ctrl+S", async () => {
fetchMock.get("https://example.com/image.png", "TESTFILE");