Implement partial download

This commit is contained in:
Hydroxycarbamide 2022-09-04 14:53:52 +02:00
parent 00bdb6c7c8
commit 59888b38dd
7 changed files with 507 additions and 5 deletions

309
src-tauri/Cargo.lock generated
View file

@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
@ -57,10 +66,13 @@ checksum = "a26fa4d7e3f2eebadf743988fc8aec9fa9a9e82611acafd77c1462ed6262440a"
name = "app"
version = "0.1.0"
dependencies = [
"error-chain",
"reqwest",
"serde",
"serde_json",
"tauri",
"tauri-build",
"tempdir",
]
[[package]]
@ -111,6 +123,21 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "base64"
version = "0.13.0"
@ -607,6 +634,25 @@ version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7"
[[package]]
name = "encoding_rs"
version = "0.8.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b"
dependencies = [
"cfg-if",
]
[[package]]
name = "error-chain"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [
"backtrace",
"version_check",
]
[[package]]
name = "fastrand"
version = "1.8.0"
@ -679,6 +725,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "futf"
version = "0.1.5"
@ -919,6 +971,12 @@ dependencies = [
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
name = "gimli"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
[[package]]
name = "gio"
version = "0.15.12"
@ -1079,6 +1137,25 @@ dependencies = [
"syn",
]
[[package]]
name = "h2"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
@ -1134,12 +1211,72 @@ dependencies = [
"itoa 1.0.3",
]
[[package]]
name = "http-body"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [
"bytes",
"http",
"pin-project-lite",
]
[[package]]
name = "http-range"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
[[package]]
name = "httparse"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "hyper"
version = "0.14.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
"httpdate",
"itoa 1.0.3",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
"want",
]
[[package]]
name = "hyper-tls"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes",
"hyper",
"native-tls",
"tokio",
"tokio-native-tls",
]
[[package]]
name = "ico"
version = "0.1.0"
@ -1235,6 +1372,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "ipnet"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
[[package]]
name = "itoa"
version = "0.4.8"
@ -1472,6 +1615,12 @@ dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "miniz_oxide"
version = "0.5.3"
@ -1481,6 +1630,18 @@ dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
]
[[package]]
name = "native-tls"
version = "0.2.10"
@ -1670,6 +1831,15 @@ dependencies = [
"objc",
]
[[package]]
name = "object"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.14.0"
@ -2059,6 +2229,19 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi",
]
[[package]]
name = "rand"
version = "0.7.3"
@ -2104,6 +2287,21 @@ dependencies = [
"rand_core 0.6.3",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.5.1"
@ -2149,6 +2347,15 @@ dependencies = [
"cty",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -2204,6 +2411,43 @@ dependencies = [
"winapi",
]
[[package]]
name = "reqwest"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"hyper",
"hyper-tls",
"ipnet",
"js-sys",
"lazy_static",
"log",
"mime",
"native-tls",
"percent-encoding",
"pin-project-lite",
"serde",
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-native-tls",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"winreg",
]
[[package]]
name = "rfd"
version = "0.9.1"
@ -2229,6 +2473,12 @@ dependencies = [
"windows 0.37.0",
]
[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustc_version"
version = "0.3.3"
@ -2901,6 +3151,16 @@ dependencies = [
"windows 0.37.0",
]
[[package]]
name = "tempdir"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
dependencies = [
"rand 0.4.6",
"remove_dir_all",
]
[[package]]
name = "tempfile"
version = "3.3.0"
@ -2995,11 +3255,38 @@ checksum = "89797afd69d206ccd11fb0ea560a44bbb87731d020670e79416d442919257d42"
dependencies = [
"autocfg",
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"once_cell",
"pin-project-lite",
"socket2",
"winapi",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
dependencies = [
"native-tls",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
"tracing",
]
[[package]]
@ -3011,6 +3298,12 @@ dependencies = [
"serde",
]
[[package]]
name = "tower-service"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
version = "0.1.36"
@ -3082,6 +3375,12 @@ dependencies = [
"serde_json",
]
[[package]]
name = "try-lock"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "typenum"
version = "1.15.0"
@ -3222,6 +3521,16 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "want"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
dependencies = [
"log",
"try-lock",
]
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"

View file

@ -16,6 +16,9 @@ tauri-build = { version = "1.0.4", features = [] }
[dependencies]
serde_json = "1.0"
tempdir = "0.3.7"
reqwest = { version = "0.11", features = ["blocking"] }
error-chain = "0.12"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.0.5", features = ["api-all"] }

View file

@ -3,8 +3,100 @@
windows_subsystem = "windows"
)]
use std::io::Cursor;
use std::path::PathBuf;
use std::io::copy;
use std::path::Path;
use std::process::Command;
use std::fs::File;
use std::io::{self, Write};
use tempdir::TempDir;
use reqwest;
mod partial_download;
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![java_version, download_revanced_cli])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
#[tauri::command]
fn java_version() -> Result<String, String> {
let stdout = match Command::new("java")
.arg("--version")
.output() {
Ok(result) => result.stdout.clone(),
Err(_e) => return Err("Java version not found".into()),
};
let s = std::str::from_utf8(&stdout)
.expect("Could not read output");
println!("{}", s);
Ok(s.into())
}
#[tauri::command]
fn download_revanced_cli() -> Result<String, String> {
let response = match download_revanced_cli_in_tmp() {
Ok(response) => response,
Err(_) => return Err("Could not create temp dir".into()),
};
Ok(response.into())
}
fn download_revanced_cli_somewhere(tmp_dir_path: &Path) -> Result<String, String> {
let target = "https://github.com/revanced/revanced-cli/releases/download/v2.9.5/revanced-cli-2.9.5-all.jar";
let fname = tmp_dir_path.join("revanced_cli.jar");
let path = fname.clone();
let string_path = path
.to_str()
.expect("Could not read path");
let dest = {
println!("will be located under: '{:?}'", fname);
match File::create(fname) {
Ok(file) => file,
Err(_) => return Err("Could not create file".to_owned()),
}
};
partial_download::download(target, &dest).;
let stdout = match Command::new("java")
.arg("-jar")
.arg(string_path)
.arg("--version")
.output() {
Ok(result) => result.stdout.clone(),
Err(_e) => return Err("revanced-cli version not found".into()),
};
let s = std::str::from_utf8(&stdout)
.expect("Could not read output");
println!("{}", s);
Ok(s.into())
}
fn download_revanced_cli_in_tmp() -> Result<String, io::Error> {
let tmp_dir = TempDir::new("example")?;
let file_path = tmp_dir.path().join("my-temporary-note.txt");
let mut tmp_file = File::create(file_path.clone())?;
writeln!(tmp_file, "Brian was here. Briefly.");
match file_path.to_str() {
None => println!("No file path for the file"),
Some(path) => println!("{}", path)
}
let response = match download_revanced_cli_somewhere(tmp_dir.path()) {
Ok(response) => response,
Err(errmsg) => panic!("{}", errmsg),
};
drop(tmp_file);
tmp_dir.close()?;
Ok(response)
}

View file

@ -0,0 +1,75 @@
use error_chain::error_chain;
use reqwest::header::{HeaderValue, CONTENT_LENGTH, RANGE};
use reqwest::StatusCode;
use std::fs::File;
use std::str::FromStr;
error_chain! {
foreign_links {
Io(std::io::Error);
Reqwest(reqwest::Error);
Header(reqwest::header::ToStrError);
}
}
struct PartialRangeIter {
start: u64,
end: u64,
buffer_size: u32,
}
impl PartialRangeIter {
pub fn new(start: u64, end: u64, buffer_size: u32) -> Result<Self> {
if buffer_size == 0 {
Err("invalid buffer_size, give a value greater than zero.")?;
}
Ok(PartialRangeIter {
start,
end,
buffer_size,
})
}
}
impl Iterator for PartialRangeIter {
type Item = HeaderValue;
fn next(&mut self) -> Option<Self::Item> {
if self.start > self.end {
None
} else {
let prev_start = self.start;
self.start += std::cmp::min(self.buffer_size as u64, self.end - self.start + 1);
Some(HeaderValue::from_str(&format!("bytes={}-{}", prev_start, self.start - 1)).expect("string provided by format!"))
}
}
}
pub fn download(url: &str, mut output_file: &File) -> Result<()> {
const CHUNK_SIZE: u32 = 2048000;
let client = reqwest::blocking::Client::new();
let response = client.head(url).send()?;
let length = response
.headers()
.get(CONTENT_LENGTH)
.ok_or("response doesn't include the content length")?;
let length = u64::from_str(length.to_str()?).map_err(|_| "invalid Content-Length header")?;
println!("starting download...");
for range in PartialRangeIter::new(0, length - 1, CHUNK_SIZE)? {
println!("range {:?}", range);
let mut response = client.get(url).header(RANGE, range).send()?;
let status = response.status();
if !(status == StatusCode::OK || status == StatusCode::PARTIAL_CONTENT) {
error_chain::bail!("Unexpected server response: {}", status)
}
std::io::copy(&mut response, &mut output_file)?;
}
let content = response.text()?;
std::io::copy(&mut content.as_bytes(), &mut output_file)?;
println!("Finished with success!");
Ok(())
}

View file

@ -1,6 +1,25 @@
<script lang="ts">
import svelteLogo from './assets/svelte.svg'
import Counter from './lib/Counter.svelte'
import { invoke } from '@tauri-apps/api/tauri';
import svelteLogo from './assets/svelte.svg';
import Counter from './lib/Counter.svelte';
let version: string = '';
const getJavaVersion = () => {
invoke('java_version')
.then((message: string) => {
version = message;
});
};
const downloadRevancedCli = () => {
invoke('download_revanced_cli')
.then((success: string) => {
version = success;
})
.catch((error: string) => {
version = error;
});
};
</script>
<main>
@ -16,6 +35,9 @@
<div class="card">
<Counter />
<button on:click={getJavaVersion}>Get java version</button>
<button on:click={downloadRevancedCli}>Download revanced</button>
<p>{version}</p>
</div>
<p>

View file

@ -1,8 +1,8 @@
import "./app.postcss";
import App from "./App.svelte";
import './app.postcss';
import App from './App.svelte';
const app = new App({
target: document.getElementById("app"),
target: document.getElementById('app'),
});
export default app;

View file

@ -1,5 +1,6 @@
const config = {
content: [
"index.html",
"./src/**/*.{html,js,svelte,ts}",
"./node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}"
],