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}