Skip to content

LargeFileUploadTask fails when uploading an attachment to an Outlook item #691

@jasonjoh

Description

@jasonjoh
async def upload_attachment_to_message(graph_client: GraphServiceClient, file_path: str) -> None:
    # <UploadAttachmentSnippet>
    # Create message
    draft_message = Message(
        subject="Large attachment"
    )

    saved_draft = await graph_client.me.messages.post(draft_message)
    if saved_draft is None or saved_draft.id is None: return

    file_stream = open(file_path, 'rb')
    total_length = os.path.getsize(file_path)

    large_attachment = AttachmentItem(
        attachment_type=AttachmentType.File,
        name=os.path.basename(file_path),
        size=total_length
    )

    # import msgraph.generated.users.item.messages.item.attachments.create_upload_session.create_upload_session_post_request_body as attachment_upload
    upload_session_body = attachment_upload.CreateUploadSessionPostRequestBody(
        attachment_item=large_attachment
    )

    upload_session = await graph_client.me.messages.by_message_id(
        saved_draft.id).attachments.create_upload_session.post(upload_session_body)

    if upload_session is None: return

    # Max slice size must be a multiple of 320 KiB
    max_slice_size = 320 * 1024
    file_upload_task = LargeFileUploadTask(
        upload_session=upload_session,
        request_adapter=graph_client.request_adapter,
        stream=file_stream, # type: ignore
        max_chunk_size=max_slice_size,
        parsable_factory=FileAttachment #type:ignore
    )

    # Create a callback that is invoked after each slice is uploaded
    def progress_callback(uploaded_byte_range: tuple[int,int]):
        print(f'Uploaded {uploaded_byte_range[0]} bytes of {total_length} bytes\n')

    try:
        upload_result = await file_upload_task.upload(progress_callback)
        if upload_result.upload_succeeded and upload_result.item_response is not None:
            file_attachment: FileAttachment = upload_result.item_response
            print(f'Upload complete, attachment ID: {file_attachment.id}')
        else:
            print('Upload failed')
    except APIError as ex:
        print(f'Error uploading attachment: {ex.message}')

On the line upload_result = await file_upload_task.upload(progress_callback) an exception is thrown.

Traceback (most recent call last):
  File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/home/jasonjoh/.vscode-server-insiders/extensions/ms-python.debugpy-2024.11.2024082901-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/__main__.py", line 71, in <module>
    cli.main()
  File "/home/jasonjoh/.vscode-server-insiders/extensions/ms-python.debugpy-2024.11.2024082901-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 486, in main
    run()
  File "/home/jasonjoh/.vscode-server-insiders/extensions/ms-python.debugpy-2024.11.2024082901-linux-x64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 336, in run_file
    runpy.run_path(target, run_name="__main__")
  File "/home/jasonjoh/.vscode-server-insiders/extensions/ms-python.debugpy-2024.11.2024082901-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 321, in run_path
    return _run_module_code(code, init_globals, run_name,
  File "/home/jasonjoh/.vscode-server-insiders/extensions/ms-python.debugpy-2024.11.2024082901-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 135, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/home/jasonjoh/.vscode-server-insiders/extensions/ms-python.debugpy-2024.11.2024082901-linux-x64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 124, in _run_code
    exec(code, run_globals)
  File "/home/jasonjoh/repos/msgraph-snippets-python/src/main.py", line 54, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "/home/jasonjoh/repos/msgraph-snippets-python/src/main.py", line 45, in main
    await LargeFileUpload.run_all_samples(user_client, large_file_settings['largeFilePath'])
  File "/home/jasonjoh/repos/msgraph-snippets-python/src/snippets/large_file_upload.py", line 22, in run_all_samples
    await LargeFileUpload.upload_attachment_to_message(graph_client, file_path)
  File "/home/jasonjoh/repos/msgraph-snippets-python/src/snippets/large_file_upload.py", line 128, in upload_attachment_to_message
    upload_result = await file_upload_task.upload(progress_callback)
  File "/home/jasonjoh/.local/lib/python3.10/site-packages/msgraph_core/tasks/large_file_upload.py", line 95, in upload
    session = await self.next_chunk(
  File "/home/jasonjoh/.local/lib/python3.10/site-packages/msgraph_core/tasks/large_file_upload.py", line 179, in next_chunk
    return await self.request_adapter.send_async(info, parsable_factory, error_map)
  File "/home/jasonjoh/.local/lib/python3.10/site-packages/kiota_http/httpx_request_adapter.py", line 176, in send_async
    response = await self.get_http_response_message(request_info, parent_span)
  File "/home/jasonjoh/.local/lib/python3.10/site-packages/kiota_http/httpx_request_adapter.py", line 542, in get_http_response_message
    return await self.retry_cae_response_if_required(resp, request_info, claims)
  File "/home/jasonjoh/.local/lib/python3.10/site-packages/kiota_http/httpx_request_adapter.py", line 559, in retry_cae_response_if_required
    raise ValueError("Unable to parse claims from response")
ValueError: Unable to parse claims from response

My suspicion is that this is similar to the problem the Go SDK had in its initial implementation: it's sending an Authorization header with each upload request: microsoftgraph/msgraph-sdk-go-core#320

I can't confirm that this is the case, but it seems likely.

Metadata

Metadata

Assignees

Labels

type:bugA broken experience

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions