Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot upload a large file to a drive #640

Closed
GFredy opened this issue Mar 25, 2024 · 4 comments
Closed

Cannot upload a large file to a drive #640

GFredy opened this issue Mar 25, 2024 · 4 comments

Comments

@GFredy
Copy link

GFredy commented Mar 25, 2024

Hello !

I'm trying to upload a file with a size that is more than 250mb to a drive.

I've been following this guide to help me : https://learn.microsoft.com/en-us/graph/sdks/large-file-upload

Unfortunately, looking at the guide, it seems that this features is only available for C#, Java, PHP and Typscript. I've been trying to find the equivalent of the LargeFileUploadTask class in the python code but i'm not finding anything.

Could someone help with this by telling me if this features is just not implemented yet or how could i do it with the python sdk.

Thanks.

@GFredy GFredy changed the title Cannot upload large files to a drive Cannot upload a large file to a drive Mar 25, 2024
@pacharlier
Copy link

pacharlier commented Mar 29, 2024

Hello,

I am trying also.

I was able to generate UploadSession but I don't know how to have kind of "LargeFileUploadTask" with the sdk.
Someone knows how to proceed ?

        body = CreateUploadSessionPostRequestBody(
            item = DriveItemUploadableProperties(
                additional_data={
                    '@microsoft.graph.conflictBehavior': 'replace'
                }
            )
        )
        
        upload_session = await graph_client.drives.by_drive_id('root').items.by_drive_item_id(file_path).create_upload_session.post(body=body)

Regards,

@pacharlier
Copy link

pacharlier commented Apr 2, 2024

Hello,

I did it by myself, I hope it will help someone else.
Here the code, once you have upload session.

    chunk = 10 * 1024 * 1024
    file_size = os.stat(file_path).st_size
    upload_url = upload_session.upload_url
    next_expected_ranges = upload_session.next_expected_ranges[0]
    
    access_token = get_access_token()
        
    with open(file_path,'rb') as my_file:
        data = my_file.read(chunk)
        while data:
            first_byte=int(next_expected_ranges.split('-')[0])
            headers = {
                "Authorization": f"Bearer {access_token}",
                "Accept": "application/json",
                "Content-Range": f"bytes {first_byte}-{first_byte + len(data) - 1}/{file_size}",
                "Content-Length": f"{len(data)}"
            }
            async with httpx.AsyncClient() as client:
                try:
                    response = await client.put(upload_url, headers=headers, content=data)

                    if response.status_code not in [200, 201, 202]:
                        raise HTTPException(status_code=response.status_code, detail=response.text)
                    if response.status_code == 201:
                        # Upload is completed, new file
                        try:
                            document = await graph_client.sites.by_site_id(site_id).items.by_base_item_id(file_path).get()
                            if document :
                                return document
                            return None
                        except APIError as e:
                            detail = f"{file_path} - {e.error.code} - {e.error.message}"
                            raise HTTPException(status_code=e.response_status_code, detail=detail)
                except httpx.HTTPError as e:
                    raise HTTPException(status_code=500, detail=f"{e}")
                except Exception as e:
                    detail = f"{type(e)} - {e}"
                    raise HTTPException(status_code=500, detail=f"{detail}")
            response_json = response.json()
            if not "nextExpectedRanges" in response_json:
                # Upload is completed, existing file
                try:
                    document_id = response_json.get('id')
                    document = await graph_client.sites.by_site_id(site_id).items.by_base_item_id(document_id).get()
                    return document
                except APIError as e:
                    detail = f"{file_path} - {e.error.code} - {e.error.message}"
                    raise HTTPException(status_code=e.response_status_code, detail=detail)
            next_expected_ranges = response_json.get('nextExpectedRanges')[0]
            data = my_file.read(chunk)

@GFredy
Copy link
Author

GFredy commented Apr 2, 2024

@pacharlier It works for me too. Thanks a lot !

For others reading this, you need these imports to make his code work.

from httpx import AsyncClient, HTTPError
from fastapi import HTTPException
from kiota_abstractions.api_error import APIError

Also here is how i create my upload session :

body = CreateUploadSessionPostRequestBody(
    item=DriveItemUploadableProperties(
        additional_data={"@microsoft.graph.conflictBehavior": "replace"}
    )
)

upload_session = (
    await self.app_client.drives.by_drive_id(driveId)
    .items.by_drive_item_id(f"{itemId}:/{filePath}:")
    .create_upload_session.post(body=body)
)

It's a good alternative while we wait for the python sdk to catch up.

@andrueastman
Copy link
Member

Currently being worked on via microsoftgraph/msgraph-sdk-python-core#530. For tracking we'll close this issue and have this issue tracked via microsoftgraph/msgraph-sdk-python-core#127

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants