How to get special app folder with the new SDK?
I am pulling my hair out trying to upload to special app folder https://docs.microsoft.com/en-us/onedrive/developer/rest-api/api/drive_get_specialfolder?view=odsp-graph-online
On 5 series, I was simply doing
val specialAppFolder = "approot" val uploadSession = graphServiceClient .me() .drive() .special(specialAppFolder) .itemWithPath(uploadDestination.removePrefix("/")) // removePrefix because OrganiserConverter.fromConfig will return /path/.. .createUploadSession(.....)
On 6+ I cannot figure-out how to get hold of specialAppFolder in order to createUploadSession().
Could someone with a better understanding point me to the right direction please?
@NLLAPPS thanks for reaching out. This should be possible via:
Drive drive = graphServiceClient.me().drive();
DriveItem specialFolder = graphServiceClient.drives().byDriveId(drive.getId()).special().byDriveItemId("{special folder name}").get();
UploadSession uploadSession = graphServiceClient.drives().byDriveId(drive.getId()).items().byDriveItemId(specialFolder.getId()).createUploadSession().post(uploadSessionRequest);
Relevant docs links: https://learn.microsoft.com/en-us/graph/api/drive-get-specialfolder?view=graph-rest-1.0&tabs=java https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0#create-an-upload-session
Thank you. I am not usually this thick but getting my head around 6 series proven to be very hard. This is what I used to to on 5 series
val uploadSession = graphServiceClient
.me()
.drive()
.special("approot")
.itemWithPath("some/sub/folder/and/filename.txt")
.createUploadSession(DriveItemCreateUploadSessionParameterSet.newBuilder().withItem(DriveItemUploadableProperties()).build())
.buildRequest(listOf<Option>(QueryOption("@name.conflictBehavior", "rename")))
Where I was able to upload "filename.txt" to ""some/sub/folder/and/" in "approot" special folder
For 6 series, I am following the guide at https://learn.microsoft.com/en-us/graph/sdks/large-file-upload?tabs=java Uploading to root with below example works fine.
val myDriveId: String = graphServiceClient.me().drive().get().id
val uploadSession = graphServiceClient.drives()
.byDriveId(myDriveId)
.items()
.byDriveItemId("root:/some/sub/folder/and/filename.txt:")
.createUploadSession()
.post(uploadSessionPostRequestBody)
But, I want to upload the file to the special "approot" folder and configure it like this:
val driveId = graphServiceClient.me().drive().get().id
val specialFolder = graphServiceClient.drives().byDriveId(driveId).special().byDriveItemId("approot").get()
val driveItem = graphServiceClient.drives()
.byDriveId(specialFolder.id)
.items()
.byDriveItemId("/some/sub/folder/and/filename.txt")
.createUploadSession()
.post(uploadSessionPostRequestBody)
Above example fails with
com.microsoft.graph.models.odataerrors.ODataError: Invalid request
Could you tell me how I am supposed to configure DriveItem name and path when uploading to special "approot" folder?
Here is the full log ` --> GET https://graph.microsoft.com/v1.0/users/TokenToReplace/drive accept: application/json authorization: Bearer xxxx --> END GET <-- 200 https://graph.microsoft.com/v1.0/users/TokenToReplace/drive (433ms) cache-control: no-store content-type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8 vary: Accept-Encoding strict-transport-security: max-age=31536000 request-id: xxxxxxxx client-request-id: xxxxxxxx odata-version: 4.0 date: Fri, 03 May 2024 09:26:44 GMT --omitted data--- <-- END HTTP (437ms, 346-byte body) --> GET https://graph.microsoft.com/v1.0/drives/xxxxxx/special/approot accept: application/json authorization: Bearer xxxx --> END GET <-- 200 https://graph.microsoft.com/v1.0/drives/xxxxxx/special/approot (137ms) --omitted data--- <-- END HTTP (145ms, 1059-byte body) --> POST https://graph.microsoft.com/v1.0/drives/xxxxxx%2111432/items/2024_05_03_09_56_59.mp3/createUploadSession Content-Length: 55 authorization: Bearer xxxx accept: application/json content-type: application/json
{"item":{"@microsoft.graph.conflictBehavior":"rename"}}
--> END POST (0-byte body)
<-- 400 https://graph.microsoft.com/v1.0/drives/xxxxxx%2111432/items/2024_05_03_09_56_59.mp3/createUploadSession (108ms)
cache-control: no-store
content-type: application/json
vary: Accept-Encoding
strict-transport-security: max-age=31536000
request-id: 3426f604xxxx
client-request-id: 3426f604xxxx
date: Fri, 03 May 2024 09:26:44 GMT
{"error":{"code":"invalidRequest","message":"Invalid request","innerError":{"date":"2024-05- 03T09:26:44","request-id":"3426f604xxxx","client-request-id":"3426f604xxxx"}}}
<-- END HTTP (114ms, 218-byte body)`
I have also dug through traffic of 5 series and noticed that
graphServiceClient .me() .drive() .special("approot").itemWithPath(uploadDestination)
Produces:
https://graph.microsoft.com/v1.0/me/drive/special/approot:/filename.txt:
But
val driveId = graphServiceClient.me().drive().get().id val specialFolder = graphServiceClient.drives().byDriveId(driveId).special().byDriveItemId("approot").get() val driveItem = graphServiceClient.drives() .byDriveId(specialFolder.id) .items() .byDriveItemId(uploadDestination)
Produces below after multple requests:
https://graph.microsoft.com/v1.0/drives/XXXXX%21XXXXX/items/filename.txt/
Isn't there any way to build
https://graph.microsoft.com/v1.0/me/drive/special/approot:/filename.txt:
Saving round trips to the API?
OK, finally fixed it! See below. I must say it was excruciatingly hard. I hope MS will consider providing upgrade path on significant changes like this in the future. Issue I had created on Feb 17 2024 at Android Samples at https://github.com/microsoftgraph/msgraph-sample-android/issues not even acknowledged yet.
val driveId = graphServiceClient.me().drive().get().id
val specialFolderId = graphServiceClient.drives().byDriveId(driveId).special().byDriveItemId("approot").get().id
val driveItemId = "${specialFolderId}:/fileName.txt:"
val uploadSession = graphServiceClient.drives().byDriveId(driveId)
.items()
.byDriveItemId(driveItemId)
.createUploadSession()
.post(uploadSessionPostRequestBody)
Above seems to create unnecessary requests. Each get() is a request to API. This was not the case in 5 series. Isn't there a way to construct Special Folder name without request to get IDs? Some sort of hand crafted DriveItemItemRequestBuilder with URL https://graph.microsoft.com/v1.0/me/drive/special/approot:/?
Are there any plans to improve the API to avoid the extra fetches? This still seems to be an issue with the latest version of the SDK (and is not an issue with version 5).
@Digipom I don't think MS accepts feedback on their SDK. This one is to watch https://github.com/openmobilehub/android-omh-auth/pull/113