1
1
import os
2
+ import uuid
3
+ from typing import IO , Callable
2
4
5
+ from office365 .runtime .client_result import ClientResult
3
6
from office365 .runtime .paths .service_operation import ServiceOperationPath
4
7
from office365 .runtime .queries .service_operation import ServiceOperationQuery
5
8
from office365 .sharepoint .entity_collection import EntityCollection
6
9
from office365 .sharepoint .files .creation_information import FileCreationInformation
7
10
from office365 .sharepoint .files .file import File
8
- from office365 .sharepoint .internal .queries .upload_session import (
9
- create_upload_session_query_ex ,
10
- )
11
11
from office365 .sharepoint .types .resource_path import ResourcePath as SPResPath
12
12
13
13
@@ -35,21 +35,59 @@ def upload(self, path_or_file):
35
35
return self .add (name , content , True )
36
36
37
37
def create_upload_session (
38
- self , path_or_file , chunk_size , chunk_uploaded = None , ** kwargs
38
+ self , file , chunk_size , chunk_uploaded = None , file_name = None , ** kwargs
39
39
):
40
+ # type: (IO|str, int, Callable[[int, ...], None], str, ...) -> File
40
41
"""Upload a file as multiple chunks
41
-
42
- :param str or typing.IO path_or_file: path where file to upload resides or file handle
42
+ :param str or typing.IO file: path where file to upload resides or file handle
43
43
:param int chunk_size: upload chunk size (in bytes)
44
44
:param (long)->None or None chunk_uploaded: uploaded event
45
+ :param str file_name: custom file name
45
46
:param kwargs: arguments to pass to chunk_uploaded function
46
47
"""
47
48
48
- qry = create_upload_session_query_ex (
49
- self , path_or_file , chunk_size , chunk_uploaded , ** kwargs
50
- )
51
- self .context .add_query (qry )
52
- return qry .return_type
49
+ auto_close = False
50
+ if not hasattr (file , "read" ):
51
+ file = open (file , "rb" )
52
+ auto_close = True
53
+
54
+ file_size = os .fstat (file .fileno ()).st_size
55
+ file_name = file_name if file_name else os .path .basename (file .name )
56
+ upload_id = str (uuid .uuid4 ())
57
+
58
+ def _upload_session (return_type , return_file ):
59
+ # type: (File|ClientResult, File) -> None
60
+ if return_file is None :
61
+ return_file = return_type
62
+
63
+ uploaded_bytes = file .tell ()
64
+ if callable (chunk_uploaded ):
65
+ chunk_uploaded (uploaded_bytes , ** kwargs )
66
+
67
+ if uploaded_bytes == file_size :
68
+ if auto_close and not file .closed :
69
+ file .close ()
70
+ return
71
+
72
+ content = file .read (chunk_size )
73
+
74
+ if uploaded_bytes == 0 :
75
+ return_file .start_upload (upload_id , content ).after_execute (
76
+ _upload_session , return_file
77
+ )
78
+ elif uploaded_bytes + len (content ) < file_size :
79
+ return_file .continue_upload (
80
+ upload_id , uploaded_bytes , content
81
+ ).after_execute (_upload_session , return_file )
82
+ else :
83
+ return_file .finish_upload (
84
+ upload_id , uploaded_bytes , content
85
+ ).after_execute (_upload_session , return_file )
86
+
87
+ if file_size > chunk_size :
88
+ return self .add (file_name , None , True ).after_execute (_upload_session , None )
89
+ else :
90
+ return self .add (file_name , file .read (), True )
53
91
54
92
def add (self , url , content , overwrite = False ):
55
93
"""
@@ -60,7 +98,7 @@ def add(self, url, content, overwrite=False):
60
98
or absolute form. Its length MUST be equal to or greater than 1.
61
99
:param bool overwrite: Specifies whether to overwrite an existing file with the same name and in the same
62
100
location as the one being added.
63
- :param str or bytes content: Specifies the binary content of the file to be added.
101
+ :param str or bytes or None content: Specifies the binary content of the file to be added.
64
102
"""
65
103
return_type = File (self .context )
66
104
self .add_child (return_type )
0 commit comments