gloo_file/object_url.rs
1use crate::{Blob, File};
2use std::{ops::Deref, rc::Rc};
3
4use wasm_bindgen::UnwrapThrowExt;
5use web_sys::Url;
6
7struct ObjectUrlAllocation {
8 url: String,
9}
10
11impl Drop for ObjectUrlAllocation {
12 fn drop(&mut self) {
13 web_sys::Url::revoke_object_url(&self.url).unwrap_throw();
14 }
15}
16
17/// A resource wrapper around [`URL.createObjectURL`] / [`URL.revokeObjectURL`].
18///
19/// A [`Blob`], in particular a [`File`], can be converted to a short URL representing its data with the above methods.
20/// An [`ObjectUrl`] can be cheaply cloned and shared and revokes the underlying URL when the last reference is dropped.
21///
22/// Note that multiple urls can be created for the same blob, without being guaranteed to be de-deduplicated.
23///
24/// # Example
25///
26/// ```rust,no_run
27/// use gloo_file::{Blob, ObjectUrl};
28///
29/// let blob = Blob::new("hello world");
30/// let object_url = ObjectUrl::from(blob);
31/// ```
32///
33/// [`URL.createObjectURL`]: https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
34/// [`URL.revokeObjectURL`]: https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
35/// [`File`]: crate::File
36#[derive(Clone)]
37pub struct ObjectUrl {
38 inner: Rc<ObjectUrlAllocation>,
39}
40
41impl From<File> for ObjectUrl {
42 fn from(file: File) -> Self {
43 Blob::from(file).into()
44 }
45}
46
47impl From<Blob> for ObjectUrl {
48 fn from(blob: Blob) -> Self {
49 web_sys::Blob::from(blob).into()
50 }
51}
52
53impl From<web_sys::Blob> for ObjectUrl {
54 fn from(blob: web_sys::Blob) -> Self {
55 let url = Url::create_object_url_with_blob(&blob).unwrap_throw();
56 let inner = Rc::new(ObjectUrlAllocation { url });
57 Self { inner }
58 }
59}
60
61// Note: some browsers support Url::create_object_url_with_source but this is deprecated!
62// https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL#using_object_urls_for_media_streams
63
64impl Deref for ObjectUrl {
65 type Target = str;
66
67 fn deref(&self) -> &Self::Target {
68 &self.inner.url
69 }
70}