Skip to content

Commit b6ca8ec

Browse files
committed
fix: use correct MIME type for file uploads
1 parent 59b4356 commit b6ca8ec

5 files changed

Lines changed: 40 additions & 17 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uipath"
3-
version = "2.0.69"
3+
version = "2.0.70"
44
description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools."
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.10"

src/uipath/_services/buckets_service.py

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import mimetypes
12
from typing import Any, Dict, Optional, Union
23

34
import httpx
@@ -154,7 +155,7 @@ def upload(
154155
key: Optional[str] = None,
155156
name: Optional[str] = None,
156157
blob_file_path: str,
157-
content_type: str,
158+
content_type: Optional[str] = None,
158159
source_path: Optional[str] = None,
159160
content: Optional[Union[str, bytes]] = None,
160161
folder_key: Optional[str] = None,
@@ -166,7 +167,7 @@ def upload(
166167
key (Optional[str]): The key of the bucket.
167168
name (Optional[str]): The name of the bucket.
168169
blob_file_path (str): The path where the file will be stored in the bucket.
169-
content_type (str): The MIME type of the file.
170+
content_type (Optional[str]): The MIME type of the file. For file inputs this is computed dynamically. Default is "application/octet-stream".
170171
source_path (Optional[str]): The local path of the file to upload.
171172
content (Optional[Union[str, bytes]]): The content to upload (string or bytes).
172173
folder_key (Optional[str]): The key of the folder where the bucket resides.
@@ -185,9 +186,17 @@ def upload(
185186
name=name, key=key, folder_key=folder_key, folder_path=folder_path
186187
)
187188

189+
# if source_path, dynamically detect the mime type
190+
# default to application/octet-stream
191+
if source_path:
192+
_content_type, _ = mimetypes.guess_type(source_path)
193+
else:
194+
_content_type = content_type
195+
_content_type = _content_type or "application/octet-stream"
196+
188197
spec = self._retrieve_writeri_spec(
189198
bucket.id,
190-
content_type,
199+
_content_type,
191200
blob_file_path,
192201
folder_key=folder_key,
193202
folder_path=folder_path,
@@ -209,6 +218,8 @@ def upload(
209218
)
210219
}
211220

221+
headers["Content-Type"] = _content_type
222+
212223
if content is not None:
213224
if isinstance(content, str):
214225
content = content.encode("utf-8")
@@ -220,13 +231,14 @@ def upload(
220231

221232
if source_path is not None:
222233
with open(source_path, "rb") as file:
234+
file_content = file.read()
223235
if result["RequiresAuth"]:
224236
self.request(
225-
"PUT", write_uri, headers=headers, files={"file": file}
237+
"PUT", write_uri, headers=headers, content=file_content
226238
)
227239
else:
228240
self.custom_client.put(
229-
write_uri, headers=headers, files={"file": file}
241+
write_uri, headers=headers, content=file_content
230242
)
231243

232244
@traced(name="buckets_upload", run_type="uipath")
@@ -237,7 +249,7 @@ async def upload_async(
237249
key: Optional[str] = None,
238250
name: Optional[str] = None,
239251
blob_file_path: str,
240-
content_type: str,
252+
content_type: Optional[str] = None,
241253
source_path: Optional[str] = None,
242254
content: Optional[Union[str, bytes]] = None,
243255
folder_key: Optional[str] = None,
@@ -249,8 +261,9 @@ async def upload_async(
249261
key (Optional[str]): The key of the bucket.
250262
name (Optional[str]): The name of the bucket.
251263
blob_file_path (str): The path where the file will be stored in the bucket.
252-
content_type (str): The MIME type of the file.
264+
content_type (Optional[str]): The MIME type of the file. For file inputs this is computed dynamically. Default is "application/octet-stream".
253265
source_path (str): The local path of the file to upload.
266+
content (Optional[Union[str, bytes]]): The content to upload (string or bytes).
254267
folder_key (Optional[str]): The key of the folder where the bucket resides.
255268
folder_path (Optional[str]): The path of the folder where the bucket resides.
256269
@@ -267,9 +280,17 @@ async def upload_async(
267280
name=name, key=key, folder_key=folder_key, folder_path=folder_path
268281
)
269282

283+
# if source_path, dynamically detect the mime type
284+
# default to application/octet-stream
285+
if source_path:
286+
_content_type, _ = mimetypes.guess_type(source_path)
287+
else:
288+
_content_type = content_type
289+
_content_type = _content_type or "application/octet-stream"
290+
270291
spec = self._retrieve_writeri_spec(
271292
bucket.id,
272-
content_type,
293+
_content_type,
273294
blob_file_path,
274295
folder_key=folder_key,
275296
folder_path=folder_path,
@@ -293,6 +314,8 @@ async def upload_async(
293314
)
294315
}
295316

317+
headers["Content-Type"] = _content_type
318+
296319
if content is not None:
297320
if isinstance(content, str):
298321
content = content.encode("utf-8")
@@ -308,13 +331,14 @@ async def upload_async(
308331

309332
if source_path is not None:
310333
with open(source_path, "rb") as file:
334+
file_content = file.read()
311335
if result["RequiresAuth"]:
312336
await self.request_async(
313-
"PUT", write_uri, headers=headers, files={"file": file}
337+
"PUT", write_uri, headers=headers, content=file_content
314338
)
315339
else:
316340
await self.custom_client_async.put(
317-
write_uri, headers=headers, files={"file": file}
341+
write_uri, headers=headers, content=file_content
318342
)
319343

320344
@traced(name="buckets_retrieve", run_type="uipath")

src/uipath/_services/context_grounding_service.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ def __init__(
5050
def add_to_index(
5151
self,
5252
name: str,
53-
content_type: str,
5453
blob_file_path: str,
54+
content_type: Optional[str] = None,
5555
content: Optional[Union[str, bytes]] = None,
5656
source_path: Optional[str] = None,
5757
folder_key: Optional[str] = None,
@@ -62,7 +62,7 @@ def add_to_index(
6262
6363
Args:
6464
name (str): The name of the index to add content to.
65-
content_type (str): The type of content being added.
65+
content_type (Optional[str]): The MIME type of the file. For file inputs this is computed dynamically. Default is "application/octet-stream".
6666
blob_file_path (str): The path where the blob will be stored in the storage bucket.
6767
content (Optional[Union[str, bytes]]): The content to be added, either as a string or bytes.
6868
source_path (Optional[str]): The source path of the content if it is being uploaded from a file.
@@ -105,8 +105,8 @@ def add_to_index(
105105
async def add_to_index_async(
106106
self,
107107
name: str,
108-
content_type: str,
109108
blob_file_path: str,
109+
content_type: Optional[str] = None,
110110
content: Optional[Union[str, bytes]] = None,
111111
source_path: Optional[str] = None,
112112
folder_key: Optional[str] = None,
@@ -117,7 +117,7 @@ async def add_to_index_async(
117117
118118
Args:
119119
name (str): The name of the index to add content to.
120-
content_type (str): The type of content being added.
120+
content_type (Optional[str]): The MIME type of the file. For file inputs this is computed dynamically. Default is "application/octet-stream".
121121
blob_file_path (str): The path where the blob will be stored in the storage bucket.
122122
content (Optional[Union[str, bytes]]): The content to be added, either as a string or bytes.
123123
source_path (Optional[str]): The source path of the content if it is being uploaded from a file.

tests/sdk/services/test_buckets_service.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,6 @@ def test_upload_from_path(
224224
assert sent_requests[2].url == "https://test-storage.com/test-file.txt"
225225

226226
assert b"test content" in sent_requests[2].content
227-
assert b"Content-Disposition: form-data;" in sent_requests[2].content
228227

229228
def test_upload_from_memory(
230229
self,

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)