Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blob & ObjecUrl generate invalid dowload link #406

Open
Tartopoms opened this issue Nov 24, 2023 · 2 comments
Open

Blob & ObjecUrl generate invalid dowload link #406

Tartopoms opened this issue Nov 24, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@Tartopoms
Copy link

Tartopoms commented Nov 24, 2023

Bug description

Either gloo::file::Blob::new(bytes.as_slice()) generated an invalid Blob,
or gloo::file::ObjectUrl::from(blob) generates an invalid ObjectUrl.
However, it works with web_sys.

Steps to Reproduce

Summary:

  1. How the download link element is created
  2. How I generate the ObjectUrl with gloo (doesn't work)
  3. How I generate the ObjectUrl with web_sys (works)

1. How the download link element is created

Download link example with Dioxus. See full example at the end

rsx!(
    a {
        href: download_url(),
        download: "sample.txt",
        "Download file"
    }
)

2. How I generate the object url with gloo (the one that failed)

use gloo::file::{Blob as gloo_Blob, ObjectUrl};
/// Generate a downlaod file url using gloo
/// /!\ Not working
pub fn download_url(blob: Vec<u8>) -> &'static str {
    let blob = gloo_Blob::new(blob.as_slice());
    let obj_url = ObjectUrl::from(blob);
    let download_url = obj_url.to_string();
    Box::leak(download_url.to_string().into_boxed_str())
}

3. How I generate the ObjectUrl with web_sys (the one that succeed)

use web_sys::{js_sys::{Uint8Array, Array}, Blob as web_sys_Blob, Url};
/// Generate a downlaod file url using web_sys
pub fn download_url(bytes: Vec<u8>) -> &'static str {
    let uint8arr = Uint8Array::new(&unsafe { Uint8Array::view(&bytes) }.into());
    let array = Array::of1(&uint8arr.buffer());
    let blob = web_sys_Blob::new_with_u8_array_sequence(&array).unwrap();
    let download_url = Url::create_object_url_with_blob(&blob).unwrap();
    Box::leak(download_url.to_string().into_boxed_str())
}

Expected Behavior

Being able to downlaod the uploaded file

Actual Behavior

Network error appear in the 'browser download' pannel instantly after download started. See image below.

Translation
"Téléchargements "-> Downloads
"Ouvrir un fichier" -> Open a file
"Impossible de télécharger - Problème de réseau" -> Cannot download - Network issue

screenshot

Full example to reproduce

The main.rs.txt file contains the code shown below.

1. Run with:

dx serve

Install dx with cargo install dioxus-cli

2. Cargo.toml

[dependencies]
dioxus-web = { version = "0.4.0" }
dioxus = { version = "0.4.0" }
gloo = { version = "0.10.0" }
web-sys = { version = "0.3.65" }

3. How-to-reproduce main.rs.txt file content:

use dioxus::prelude::*;
use gloo::file::{Blob as gloo_Blob, ObjectUrl};
use web_sys::{js_sys::{Array, Uint8Array},Blob as web_sys_Blob, Url,};

fn main() {
    dioxus_web::launch(app);
}

fn app(cx: Scope) -> Element {
    // Shared value for file name, and content
    let filename = use_state(cx, String::new);
    let filecontent = use_state(cx, Vec::<u8>::new);

    // Closure for onchange file input handler
    let file_input_onchange = |evt: Event<FormData>| {
        to_owned![filename];
        to_owned![filecontent];
        async move {
            let file_engine = &evt.files.clone().expect("Failed to get file_engine");
            let files = file_engine.files();
            let name = files.get(0).expect("Failed to get the uploaded file");
            let content = file_engine
                .read_file(name)
                .await
                .expect("Failed to read file");
            filename.set(name.clone());
            filecontent.set(content);
        }
    };

    render! {
        // upload file input, takes a onchange handler closure to retrieve the file name and blob
        input {
            r#type: "file",
            onchange: file_input_onchange,
        }
        // will spawn two download button when a file is uploaded
        if !filename.is_empty() && !filecontent.is_empty() {
            rsx!(
                ul {
                    li {
                        a {
                            href: gloo_download_url(filecontent.get().clone()),
                            download: "{filename.get().clone()}",
                            "gloo download of {filename.get().clone()}"
                        }
                    }
                    li {
                        a {
                            href: web_sys_download_url(filecontent.get().clone()),
                            download: "{filename.get().clone()}",
                            "web_sys download of {filename.get().clone()}"
                        }
                    }
                }
            )
        }
    }
}

/// Generate a downlaod file url using gloo
/// /!\ Not working
pub fn gloo_download_url(blob: Vec<u8>) -> &'static str {
    let blob = gloo_Blob::new(blob.as_slice());
    let obj_url = ObjectUrl::from(blob);
    let download_url = obj_url.to_string();
    Box::leak(download_url.to_string().into_boxed_str())
}

/// Generate a downlaod file url using web_sys
pub fn web_sys_download_url(bytes: Vec<u8>) -> &'static str {
    let uint8arr = Uint8Array::new(&unsafe { Uint8Array::view(&bytes) }.into());
    let array = Array::of1(&uint8arr.buffer());
    let blob = web_sys_Blob::new_with_u8_array_sequence(&array).unwrap();
    let download_url = Url::create_object_url_with_blob(&blob).unwrap();
    Box::leak(download_url.to_string().into_boxed_str())
}
@Tartopoms Tartopoms added the bug Something isn't working label Nov 24, 2023
@dmatos2012
Copy link

Did you figure this out @Tartopoms. I am using firefox and the web_sys_download_url works fine, but yours or the slightly different,

let blob = Blob::new_with_options(byte_slice, Some("application/pdf"));
let object_url = ObjectUrl::from(blob);
let download_url = object_url.to_string();

fails with
Security Error: Content at http:localhost:XXXXXXXX may not load data from blob:http:localhost:XXXX`, which is probably the same error you got but with the GUI.

@Tartopoms
Copy link
Author

@dmatos2012, I didn't figure it out, I stuck to the web_sys solution because it wasn't a major problem to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants