feat: cli multipart uploads (#33546)

This commit is contained in:
David Newell
2025-06-12 09:36:05 +01:00
committed by GitHub
parent 29193ac5ad
commit d608debc32
4 changed files with 356 additions and 423 deletions

756
cli/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -34,6 +34,7 @@ serde_json = "1.0.140"
reqwest = { version = "0.12.14", features = [
"blocking",
"json",
"multipart",
"rustls-tls",
], default-features = false }
anyhow = "1.0.97"

View File

@@ -72,18 +72,20 @@ fn upload_chunks(
for upload in uploads {
info!("Uploading chunk {}", upload.chunk_id);
let mut params = vec![("chunk_id", &upload.chunk_id)];
let mut params: Vec<(&'static str, &str)> =
vec![("chunk_id", &upload.chunk_id), ("multipart", "true")];
if let Some(id) = &release_id {
params.push(("release_id", id));
}
let part = reqwest::blocking::multipart::Part::bytes(upload.data).file_name("file");
let form = reqwest::blocking::multipart::Form::new().part("file", part);
let res = client
.post(url)
.multipart(form)
.header("Authorization", format!("Bearer {}", token))
.header("Content-Type", "application/octet-stream")
.header("Content-Disposition", "attachment; filename='chunk'")
.query(&params)
.body(upload.data)
.send()
.context(format!("While uploading chunk to {}", url))?;

View File

@@ -473,11 +473,19 @@ class ErrorTrackingSymbolSetViewSet(TeamAndOrgViewSetMixin, viewsets.ModelViewSe
def create(self, request, *args, **kwargs) -> Response:
# pull the symbol set reference from the query params
chunk_id = request.query_params.get("chunk_id", None)
multipart = request.query_params.get("multipart", False)
if not chunk_id:
return Response({"detail": "chunk_id query parameter is required"}, status=status.HTTP_400_BAD_REQUEST)
# file added to the request data by the FileUploadParser
data = request.data["file"].read()
if multipart:
data = bytearray()
for chunk in request.FILES["file"].chunks():
data.extend(chunk)
else:
# legacy: older versions of the CLI did not use multipart uploads
# file added to the request data by the FileUploadParser
data = request.data["file"].read()
(storage_ptr, content_hash) = upload_content(bytearray(data))
release_id = request.query_params.get("release_id", None)