9dfa06ffee
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Signed-off-by: cls_宁波本机 <908705107@qq.com>
97 lines
2.9 KiB
Rust
97 lines
2.9 KiB
Rust
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
|
|
use tauri::{
|
|
ipc::{InvokeBody, Request},
|
|
State,
|
|
};
|
|
|
|
use crate::app_state::AppState;
|
|
|
|
use super::{
|
|
media::{upload_media_bytes_inner, BlobDescriptor},
|
|
media_upload_progress::{
|
|
begin_media_upload, cancel_media_upload as cancel_registered_media_upload,
|
|
finish_media_upload,
|
|
},
|
|
};
|
|
|
|
/// Upload raw bytes directly (for paste and drag-drop).
|
|
///
|
|
/// The renderer already has the bytes in memory from the clipboard/drag event.
|
|
/// If the bytes are a video, they're written to a temp file, transcoded via
|
|
/// ffmpeg, and the transcoded output is uploaded instead.
|
|
#[tauri::command]
|
|
pub async fn upload_media_bytes(
|
|
data: Vec<u8>,
|
|
filename: Option<String>,
|
|
progress_id: Option<String>,
|
|
app: tauri::AppHandle,
|
|
state: State<'_, AppState>,
|
|
) -> Result<BlobDescriptor, String> {
|
|
upload_media_bytes_inner(data, filename, progress_id, app, state, None).await
|
|
}
|
|
|
|
fn decode_raw_upload_header(value: &str) -> Result<String, String> {
|
|
let bytes = URL_SAFE_NO_PAD
|
|
.decode(value)
|
|
.map_err(|error| format!("invalid raw upload header: {error}"))?;
|
|
String::from_utf8(bytes).map_err(|error| format!("invalid raw upload header text: {error}"))
|
|
}
|
|
|
|
fn optional_raw_upload_header(request: &Request<'_>, name: &str) -> Result<Option<String>, String> {
|
|
request
|
|
.headers()
|
|
.get(name)
|
|
.map(|value| {
|
|
value
|
|
.to_str()
|
|
.map_err(|error| format!("invalid {name} header: {error}"))
|
|
.and_then(decode_raw_upload_header)
|
|
})
|
|
.transpose()
|
|
}
|
|
|
|
/// Cancel the native upload associated with a background progress ID.
|
|
#[tauri::command]
|
|
pub fn cancel_media_upload(progress_id: String) {
|
|
cancel_registered_media_upload(&progress_id);
|
|
}
|
|
|
|
/// Upload raw IPC bytes without expanding a large browser File into JSON.
|
|
#[tauri::command]
|
|
pub async fn upload_media_bytes_raw(
|
|
request: Request<'_>,
|
|
app: tauri::AppHandle,
|
|
state: State<'_, AppState>,
|
|
) -> Result<BlobDescriptor, String> {
|
|
let data = match request.body() {
|
|
InvokeBody::Raw(data) => data.clone(),
|
|
InvokeBody::Json(_) => return Err("raw upload requires a byte body".to_string()),
|
|
};
|
|
let filename = optional_raw_upload_header(&request, "x-buzz-filename")?;
|
|
let progress_id = optional_raw_upload_header(&request, "x-buzz-progress-id")?;
|
|
|
|
let cancellation = begin_media_upload(progress_id.as_deref());
|
|
let result = upload_media_bytes_inner(
|
|
data,
|
|
filename,
|
|
progress_id.clone(),
|
|
app,
|
|
state,
|
|
cancellation.as_ref(),
|
|
)
|
|
.await;
|
|
finish_media_upload(progress_id.as_deref());
|
|
result
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_decode_raw_upload_header_preserves_unicode() {
|
|
let encoded = URL_SAFE_NO_PAD.encode("clip 🎬.mp4");
|
|
assert_eq!(decode_raw_upload_header(&encoded).unwrap(), "clip 🎬.mp4");
|
|
}
|
|
}
|