@@ -117,6 +117,52 @@ def __init__(
117117 self .content_modified_at = content_modified_at
118118
119119
120+ class UploadWithPreflightCheckAttributesParentField (BaseObject ):
121+ def __init__ (self , id : str , ** kwargs ):
122+ """
123+ :param id: The id of the parent folder. Use
124+ `0` for the user's root folder.
125+ :type id: str
126+ """
127+ super ().__init__ (** kwargs )
128+ self .id = id
129+
130+
131+ class UploadWithPreflightCheckAttributes (BaseObject ):
132+ def __init__ (
133+ self ,
134+ name : str ,
135+ parent : UploadWithPreflightCheckAttributesParentField ,
136+ size : int ,
137+ * ,
138+ content_created_at : Optional [DateTime ] = None ,
139+ content_modified_at : Optional [DateTime ] = None ,
140+ ** kwargs
141+ ):
142+ """
143+ :param name: The name of the file
144+ :type name: str
145+ :param parent: The parent folder to upload the file to
146+ :type parent: UploadWithPreflightCheckAttributesParentField
147+ :param size: The size of the file in bytes
148+ :type size: int
149+ :param content_created_at: Defines the time the file was originally created at.
150+
151+ If not set, the upload time will be used., defaults to None
152+ :type content_created_at: Optional[DateTime], optional
153+ :param content_modified_at: Defines the time the file was last modified at.
154+
155+ If not set, the upload time will be used., defaults to None
156+ :type content_modified_at: Optional[DateTime], optional
157+ """
158+ super ().__init__ (** kwargs )
159+ self .name = name
160+ self .parent = parent
161+ self .size = size
162+ self .content_created_at = content_created_at
163+ self .content_modified_at = content_modified_at
164+
165+
120166class UploadsManager :
121167 def __init__ (
122168 self ,
@@ -246,15 +292,12 @@ def upload_file_version(
246292 params = query_params_map ,
247293 headers = headers_map ,
248294 multipart_data = [
249- MultipartItem (
250- part_name = 'attributes' ,
251- data = serialize (request_body .get ('attributes' )),
252- ),
295+ MultipartItem (part_name = 'attributes' , data = serialize (attributes )),
253296 MultipartItem (
254297 part_name = 'file' ,
255- file_stream = request_body . get ( ' file' ) ,
256- file_name = request_body . get ( ' file_file_name' ) ,
257- content_type = request_body . get ( ' file_content_type' ) ,
298+ file_stream = file ,
299+ file_name = file_file_name ,
300+ content_type = file_content_type ,
258301 ),
259302 ],
260303 content_type = 'multipart/form-data' ,
@@ -394,15 +437,98 @@ def upload_file(
394437 params = query_params_map ,
395438 headers = headers_map ,
396439 multipart_data = [
440+ MultipartItem (part_name = 'attributes' , data = serialize (attributes )),
397441 MultipartItem (
398- part_name = 'attributes' ,
399- data = serialize (request_body .get ('attributes' )),
442+ part_name = 'file' ,
443+ file_stream = file ,
444+ file_name = file_file_name ,
445+ content_type = file_content_type ,
400446 ),
447+ ],
448+ content_type = 'multipart/form-data' ,
449+ response_format = ResponseFormat .JSON ,
450+ auth = self .auth ,
451+ network_session = self .network_session ,
452+ )
453+ )
454+ return deserialize (response .data , Files )
455+
456+ def upload_with_preflight_check (
457+ self ,
458+ attributes : UploadWithPreflightCheckAttributes ,
459+ file : ByteStream ,
460+ * ,
461+ file_file_name : Optional [str ] = None ,
462+ file_content_type : Optional [str ] = None ,
463+ fields : Optional [List [str ]] = None ,
464+ content_md_5 : Optional [str ] = None ,
465+ extra_headers : Optional [Dict [str , Optional [str ]]] = None
466+ ) -> Files :
467+ """
468+ Upload a file with a preflight check
469+ :param file: The content of the file to upload to Box.
470+
471+ <Message warning>
472+
473+ The `attributes` part of the body must come **before** the
474+ `file` part. Requests that do not follow this format when
475+ uploading the file will receive a HTTP `400` error with a
476+ `metadata_after_file_contents` error code.
477+
478+ </Message>
479+ :type file: ByteStream
480+ :param fields: A comma-separated list of attributes to include in the
481+ response. This can be used to request fields that are
482+ not normally returned in a standard response.
483+
484+ Be aware that specifying this parameter will have the
485+ effect that none of the standard fields are returned in
486+ the response unless explicitly specified, instead only
487+ fields for the mini representation are returned, additional
488+ to the fields requested., defaults to None
489+ :type fields: Optional[List[str]], optional
490+ :param content_md_5: An optional header containing the SHA1 hash of the file to
491+ ensure that the file was not corrupted in transit., defaults to None
492+ :type content_md_5: Optional[str], optional
493+ :param extra_headers: Extra headers that will be included in the HTTP request., defaults to None
494+ :type extra_headers: Optional[Dict[str, Optional[str]]], optional
495+ """
496+ if extra_headers is None :
497+ extra_headers = {}
498+ request_body : Dict = {
499+ 'attributes' : attributes ,
500+ 'file' : file ,
501+ 'file_file_name' : file_file_name ,
502+ 'file_content_type' : file_content_type ,
503+ }
504+ query_params_map : Dict [str , str ] = prepare_params ({'fields' : to_string (fields )})
505+ headers_map : Dict [str , str ] = prepare_params (
506+ {'content-md5' : to_string (content_md_5 ), ** extra_headers }
507+ )
508+ preflight_upload_url : UploadUrl = self .preflight_file_upload_check (
509+ name = attributes .name ,
510+ size = attributes .size ,
511+ parent = PreflightFileUploadCheckParent (id = attributes .parent .id ),
512+ extra_headers = extra_headers ,
513+ )
514+ if (
515+ preflight_upload_url .upload_url == None
516+ or not 'http' in preflight_upload_url .upload_url
517+ ):
518+ raise BoxSDKError (message = 'Unable to get preflight upload URL' )
519+ response : FetchResponse = self .network_session .network_client .fetch (
520+ FetchOptions (
521+ url = preflight_upload_url .upload_url ,
522+ method = 'POST' ,
523+ params = query_params_map ,
524+ headers = headers_map ,
525+ multipart_data = [
526+ MultipartItem (part_name = 'attributes' , data = serialize (attributes )),
401527 MultipartItem (
402528 part_name = 'file' ,
403- file_stream = request_body . get ( ' file' ) ,
404- file_name = request_body . get ( ' file_file_name' ) ,
405- content_type = request_body . get ( ' file_content_type' ) ,
529+ file_stream = file ,
530+ file_name = file_file_name ,
531+ content_type = file_content_type ,
406532 ),
407533 ],
408534 content_type = 'multipart/form-data' ,
0 commit comments