Skip to content

Commit 80d5bb3

Browse files
committed
misc: Use filename when uploading unencrypted media
This will rename the uploaded file in the media server so it references the original one.
1 parent 8ad785a commit 80d5bb3

File tree

8 files changed

+60
-16
lines changed

8 files changed

+60
-16
lines changed

crates/matrix-sdk-base/src/media.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ pub trait MediaEventContent {
142142
/// Returns `None` if `Self` has no file.
143143
fn source(&self) -> Option<MediaSource>;
144144

145+
/// Get the name of the uploaded file for `Self`.
146+
fn filename(&self) -> Option<String>;
147+
145148
/// Get the source of the thumbnail for `Self`.
146149
///
147150
/// Returns `None` if `Self` has no thumbnail.
@@ -153,6 +156,10 @@ impl MediaEventContent for StickerEventContent {
153156
Some(MediaSource::from(self.source.clone()))
154157
}
155158

159+
fn filename(&self) -> Option<String> {
160+
None
161+
}
162+
156163
fn thumbnail_source(&self) -> Option<MediaSource> {
157164
None
158165
}
@@ -163,6 +170,10 @@ impl MediaEventContent for AudioMessageEventContent {
163170
Some(self.source.clone())
164171
}
165172

173+
fn filename(&self) -> Option<String> {
174+
self.filename.clone()
175+
}
176+
166177
fn thumbnail_source(&self) -> Option<MediaSource> {
167178
None
168179
}
@@ -173,6 +184,10 @@ impl MediaEventContent for FileMessageEventContent {
173184
Some(self.source.clone())
174185
}
175186

187+
fn filename(&self) -> Option<String> {
188+
self.filename.clone()
189+
}
190+
176191
fn thumbnail_source(&self) -> Option<MediaSource> {
177192
self.info.as_ref()?.thumbnail_source.clone()
178193
}
@@ -183,6 +198,10 @@ impl MediaEventContent for ImageMessageEventContent {
183198
Some(self.source.clone())
184199
}
185200

201+
fn filename(&self) -> Option<String> {
202+
self.filename.clone()
203+
}
204+
186205
fn thumbnail_source(&self) -> Option<MediaSource> {
187206
self.info
188207
.as_ref()
@@ -196,6 +215,10 @@ impl MediaEventContent for VideoMessageEventContent {
196215
Some(self.source.clone())
197216
}
198217

218+
fn filename(&self) -> Option<String> {
219+
self.filename.clone()
220+
}
221+
199222
fn thumbnail_source(&self) -> Option<MediaSource> {
200223
self.info
201224
.as_ref()
@@ -209,6 +232,10 @@ impl MediaEventContent for LocationMessageEventContent {
209232
None
210233
}
211234

235+
fn filename(&self) -> Option<String> {
236+
None
237+
}
238+
212239
fn thumbnail_source(&self) -> Option<MediaSource> {
213240
self.info.as_ref()?.thumbnail_source.clone()
214241
}

crates/matrix-sdk-ui/src/timeline/mod.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -821,21 +821,24 @@ pub enum AttachmentSource {
821821
/// An attachment loaded from a file.
822822
///
823823
/// The bytes and the filename will be read from the file at the given path.
824-
File(PathBuf),
824+
File { filename: Option<String>, path: PathBuf },
825825
}
826826

827827
impl AttachmentSource {
828828
/// Try to convert this attachment source into a `(bytes, filename)` tuple.
829829
pub(crate) fn try_into_bytes_and_filename(self) -> Result<(Vec<u8>, String), Error> {
830830
match self {
831831
Self::Data { bytes, filename } => Ok((bytes, filename)),
832-
Self::File(path) => {
833-
let filename = path
834-
.file_name()
835-
.ok_or(Error::InvalidAttachmentFileName)?
836-
.to_str()
837-
.ok_or(Error::InvalidAttachmentFileName)?
838-
.to_owned();
832+
Self::File { path, filename } => {
833+
let filename = if let Some(filename) = filename {
834+
filename
835+
} else {
836+
path.file_name()
837+
.ok_or(Error::InvalidAttachmentFileName)?
838+
.to_str()
839+
.ok_or(Error::InvalidAttachmentFileName)?
840+
.to_owned()
841+
};
839842
let bytes = fs::read(&path).map_err(|_| Error::InvalidAttachmentData)?;
840843
Ok((bytes, filename))
841844
}
@@ -848,7 +851,7 @@ where
848851
P: Into<PathBuf>,
849852
{
850853
fn from(value: P) -> Self {
851-
Self::File(value.into())
854+
Self::File { path: value.into(), filename: None }
852855
}
853856
}
854857

crates/matrix-sdk/src/account.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ impl Account {
264264
///
265265
/// [`Media::upload()`]: crate::Media::upload
266266
pub async fn upload_avatar(&self, content_type: &Mime, data: Vec<u8>) -> Result<OwnedMxcUri> {
267-
let upload_response = self.client.media().upload(content_type, data, None).await?;
267+
let upload_response = self.client.media().upload(content_type, data, None, None).await?;
268268
self.set_avatar_url(Some(&upload_response.content_uri)).await?;
269269
Ok(upload_response.content_uri)
270270
}

crates/matrix-sdk/src/encryption/futures.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ where
9191

9292
let response = client
9393
.media()
94-
.upload(&mime::APPLICATION_OCTET_STREAM, buf, request_config)
94+
.upload(&mime::APPLICATION_OCTET_STREAM, buf, None, request_config)
9595
.with_send_progress_observable(send_progress)
9696
.await?;
9797

crates/matrix-sdk/src/media.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,10 @@ impl Media {
190190
/// # let mut client = Client::new(homeserver).await?;
191191
/// let image = fs::read("/home/example/my-cat.jpg")?;
192192
///
193-
/// let response =
194-
/// client.media().upload(&mime::IMAGE_JPEG, image, None).await?;
193+
/// let response = client
194+
/// .media()
195+
/// .upload(&mime::IMAGE_JPEG, image, Some("my-cat.jpg".to_string()), None)
196+
/// .await?;
195197
///
196198
/// println!("Cat URI: {}", response.content_uri);
197199
/// # anyhow::Ok(()) };
@@ -200,13 +202,15 @@ impl Media {
200202
&self,
201203
content_type: &Mime,
202204
data: Vec<u8>,
205+
filename: Option<String>,
203206
request_config: Option<RequestConfig>,
204207
) -> SendMediaUploadRequest {
205208
let request_config = request_config.unwrap_or_else(|| {
206209
self.client.request_config().timeout(Self::reasonable_upload_timeout(&data))
207210
});
208211

209212
let request = assign!(media::create_content::v3::Request::new(data), {
213+
filename,
210214
content_type: Some(content_type.essence_str().to_owned()),
211215
});
212216

@@ -721,13 +725,16 @@ impl Media {
721725
&self,
722726
content_type: &Mime,
723727
data: Vec<u8>,
728+
filename: Option<String>,
724729
thumbnail: Option<Thumbnail>,
725730
send_progress: SharedObservable<TransmissionProgress>,
726731
) -> Result<(MediaSource, Option<(MediaSource, Box<ThumbnailInfo>)>)> {
727732
let upload_thumbnail = self.upload_thumbnail(thumbnail, send_progress.clone());
728733

729734
let upload_attachment = async move {
730-
self.upload(content_type, data, None).with_send_progress_observable(send_progress).await
735+
self.upload(content_type, data, filename, None)
736+
.with_send_progress_observable(send_progress)
737+
.await
731738
};
732739

733740
let (thumbnail, response) = try_join(upload_thumbnail, upload_attachment).await?;
@@ -749,7 +756,7 @@ impl Media {
749756
let (data, content_type, thumbnail_info) = thumbnail.into_parts();
750757

751758
let response = self
752-
.upload(&content_type, data, None)
759+
.upload(&content_type, data, None, None)
753760
.with_send_progress_observable(send_progress)
754761
.await?;
755762
let url = response.content_uri;

crates/matrix-sdk/src/room/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2247,6 +2247,7 @@ impl Room {
22472247
// TODO: get rid of this clone; wait for Ruma to use `Bytes` or something
22482248
// similar.
22492249
data.clone(),
2250+
Some(filename.clone()),
22502251
thumbnail,
22512252
send_progress,
22522253
)
@@ -2514,7 +2515,7 @@ impl Room {
25142515
) -> Result<send_state_event::v3::Response> {
25152516
self.ensure_room_joined()?;
25162517

2517-
let upload_response = self.client.media().upload(mime, data, None).await?;
2518+
let upload_response = self.client.media().upload(mime, data, None, None).await?;
25182519
let mut info = info.unwrap_or_default();
25192520
info.blurhash = upload_response.blurhash;
25202521
info.mimetype = Some(mime.to_string());

crates/matrix-sdk/src/test_utils/mocks/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2444,6 +2444,11 @@ impl<'a> MockEndpoint<'a, UploadEndpoint> {
24442444
Self { mock: self.mock.and(header("content-type", content_type)), ..self }
24452445
}
24462446

2447+
/// Expect the filename query param to match the provided value.
2448+
pub fn expect_filename(self, filename: &str) -> Self {
2449+
Self { mock: self.mock.and(query_param("filename", filename)), ..self }
2450+
}
2451+
24472452
/// Returns a redact endpoint that emulates success, i.e. the redaction
24482453
/// event has been sent with the given event id.
24492454
pub fn ok(self, mxc_id: &MxcUri) -> MatrixMock<'a> {

crates/matrix-sdk/tests/integration/room/attachment/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ async fn test_room_attachment_send_info() {
120120

121121
mock.mock_upload()
122122
.expect_mime_type("image/jpeg")
123+
.expect_filename("image.jpg")
123124
.ok(mxc_uri!("mxc://example.com/AQwafuaFswefuhsfAFAgsw"))
124125
.mock_once()
125126
.mount()

0 commit comments

Comments
 (0)