# 05 — Medien & Dateien --- ## Inhaltsverzeichnis - [Datei hochladen](#datei-hochladen) - [Bild senden](#bild-senden) - [Video senden](#video-senden) - [Audio / Sprachnachricht senden](#audio--sprachnachricht-senden) - [Datei senden](#datei-senden) - [Sticker senden](#sticker-senden) - [Medien herunterladen & entschlüsseln](#medien-herunterladen--entschlüsseln) - [Thumbnails & Vorschaubilder](#thumbnails--vorschaubilder) - [MXC-URL zu HTTP-URL](#mxc-url-zu-http-url) - [Verschlüsselte Medien](#verschlüsselte-medien) - [Avatar hochladen](#avatar-hochladen) - [MatrixFile-Objekte](#matrixfile-objekte) --- ## Datei hochladen ```dart // Bytes hochladen → mxc:// URI zurück final mxcUri = await client.uploadContent( fileBytes, // Uint8List filename: 'datei.pdf', contentType: 'application/pdf', // optional, SDK erkennt es ); print(mxcUri); // mxc://example.org/AbCdEf... ``` --- ## Bild senden ```dart import 'package:matrix/matrix.dart'; // MatrixImageFile erstellen final imageFile = MatrixImageFile( bytes: imageBytes, // Uint8List name: 'foto.jpg', mimeType: 'image/jpeg', width: 1920, // optional, für Info height: 1080, ); // Mit Thumbnail final thumbnail = MatrixImageFile( bytes: thumbnailBytes, name: 'foto_thumb.jpg', mimeType: 'image/jpeg', width: 320, height: 180, ); // Senden (lädt automatisch hoch + sendet m.image Event) await room.sendFileEvent( imageFile, thumbnail: thumbnail, // optional ); // Alternativ mit sendImageEvent await room.sendImageEvent( imageFile, thumbnail: thumbnail, ); ``` --- ## Video senden ```dart final videoFile = MatrixVideoFile( bytes: videoBytes, name: 'video.mp4', mimeType: 'video/mp4', duration: 45000, // Millisekunden width: 1920, height: 1080, ); final thumbFile = MatrixImageFile( bytes: thumbnailBytes, name: 'thumb.jpg', mimeType: 'image/jpeg', width: 320, height: 180, ); await room.sendVideoEvent( videoFile, thumbnail: thumbFile, ); ``` --- ## Audio / Sprachnachricht senden ```dart // Audio-Datei final audioFile = MatrixAudioFile( bytes: audioBytes, name: 'aufnahme.ogg', mimeType: 'audio/ogg', duration: 12000, // Millisekunden ); await room.sendAudioEvent(audioFile); // Sprachnachricht (Voice Message MSC3245) await room.sendFileEvent( audioFile, extraContent: { 'org.matrix.msc3245.voice': {}, // markiert als Sprachnachricht 'org.matrix.msc1767.audio': { 'duration': 12000, 'waveform': [0, 50, 100, 75, ...], // Amplituden (0-1024) }, }, ); ``` --- ## Datei senden ```dart final file = MatrixFile( bytes: fileBytes, name: 'dokument.pdf', mimeType: 'application/pdf', ); await room.sendFileEvent(file); // Mit Extra-Metadaten await room.sendFileEvent( file, extraContent: { 'org.matrix.msc3554.caption': { 'msgtype': 'm.text', 'body': 'Hier das Dokument', }, }, ); ``` --- ## Sticker senden ```dart // Sticker sind ein eigener Event-Typ (m.sticker) await room.sendEvent( { 'body': 'Ein Sticker', 'url': 'mxc://example.org/stickerId', 'info': { 'mimetype': 'image/png', 'w': 256, 'h': 256, }, }, EventTypes.Sticker, // 'm.sticker' ); ``` --- ## Medien herunterladen & entschlüsseln ```dart // Aus Event-Attachment herunterladen (+ automatisch entschlüsseln bei E2EE) final data = await event.downloadAndDecryptAttachment( getThumbnail: false, // true für Thumbnail statt Original ); // data ist MatrixFile mit .bytes: Uint8List // Direkte MXC-URL herunterladen final bytes = await client.database.getFile(mxcUri); // oder über HTTP: final httpUri = mxcUri.getDownloadUri(client); // → https://homeserver/_matrix/media/v3/download/server/mediaId ``` --- ## Thumbnails & Vorschaubilder ```dart // Thumbnail-URL für Widget final thumbnailUri = event.thumbnailUrl; // mxc:// URI // HTTP-URL für Thumbnail (mit Größe) final httpUrl = thumbnailUri?.getThumbnail( client, width: 800, height: 600, method: ThumbnailMethod.scale, // oder .crop ); // Avatar-Thumbnail final avatarUrl = user.avatarUrl?.getThumbnail( client, width: 56, height: 56, method: ThumbnailMethod.crop, ); // Im Flutter Widget (CachedNetworkImage o.ä.): Image.network(httpUrl.toString()); ``` --- ## MXC-URL zu HTTP-URL ```dart // Download-URL final downloadUrl = Uri.parse(mxcUriString).getDownloadUri(client); // → https://homeserver/_matrix/media/v3/download/server/mediaId // Thumbnail-URL final thumbUrl = Uri.parse(mxcUriString).getThumbnail( client, width: 300, height: 300, method: ThumbnailMethod.crop, ); // Direkt als String final urlString = downloadUrl.toString(); ``` --- ## Verschlüsselte Medien ```dart // In verschlüsselten Räumen werden Medien automatisch verschlüsselt. // Das SDK übernimmt Ver- und Entschlüsselung transparent. // Verschlüsselter Download (automatisch): final file = await event.downloadAndDecryptAttachment(); // file.bytes enthält die entschlüsselten Rohdaten // Manuell ver-/entschlüsseln (selten nötig): // Nutze EncryptedFile aus dem matrix-package final encryptedFile = EncryptedFile( url: 'mxc://...', key: {/* JWK */}, iv: 'base64...', hashes: {'sha256': 'base64...'}, v: 'v2', ); ``` --- ## Avatar hochladen ```dart // Eigener Avatar final avatarBytes = await File('avatar.png').readAsBytes(); final mxcUri = await client.uploadContent( avatarBytes, filename: 'avatar.png', contentType: 'image/png', ); await client.setAvatarUrl(client.userID!, mxcUri); // Raum-Avatar final roomAvatarMxc = await client.uploadContent(imageBytes, filename: 'room.png'); await room.setAvatar(roomAvatarMxc); ``` --- ## MatrixFile-Objekte ```dart // Basis-Klasse MatrixFile({ required Uint8List bytes, required String name, String? mimeType, }) // Spezialisierte Unterklassen: MatrixImageFile({ required Uint8List bytes, required String name, String? mimeType, // z.B. 'image/jpeg' int? width, int? height, bool? animated, // für GIFs }) MatrixVideoFile({ required Uint8List bytes, required String name, String? mimeType, // 'video/mp4' int? duration, // ms int? width, int? height, MatrixImageFile? thumbnail, }) MatrixAudioFile({ required Uint8List bytes, required String name, String? mimeType, // 'audio/ogg' int? duration, // ms }) // Eigenschaften file.bytes // Uint8List file.name // Dateiname file.mimeType // MIME-Typ file.sizeString // '1.4 MB' (formatiert) file.size // Bytes als int ``` --- ## Medien-Events lesen ```dart // Attachment-Info aus Event if (event.messageType == 'm.image') { final url = event.attachmentMxcUrl; // mxc:// URI final mime = event.attachmentMimetype; // 'image/jpeg' final size = event.attachmentSize; // Bytes final width = event.infoMap['w'] as int?; final height = event.infoMap['h'] as int?; } if (event.messageType == 'm.video') { final duration = event.infoMap['duration'] as int?; // ms } if (event.messageType == 'm.audio') { final duration = event.infoMap['duration'] as int?; final waveform = event.content .tryGetMap('org.matrix.msc1767.audio') ?.tryGetList('waveform'); } // Datei-Größe als lesbarer String print(event.sizeString); // '2.3 MB' ```