如何使用 MS Graph 指定将文件上传到 OneDrive 的流

问题描述:

我正在使用 Angular 9 使用 MS Graph 将文件上传到 OneDrive.

I am working with Angular 9 to upload a file to OneDrive using MS Graph.

我上传了一个空文件并上传了一个包含一些虚假内容(数据类型)的文件.我想我没有添加正确的流,

I got so far as to upload an empty file and upload a file with some bogus content (the datatype). I suppose I am not adding the right stream,

我阅读了上传或替换 DriveItem 的内容"和另一堆文档.它说:请求正文的内容应该是要上传的文件的二进制流.

I read "Upload or replace the contents of a DriveItem" and another bunch of documents. it says: The contents of the request body should be the binary stream of the file to be uploaded.

在同一个文档中,在示例(更新现有文件)部分中,它说:

In the same document, in the Example (updating an existing file) section it says:

const stream = The contents of the file goes here.; 
let res = await client.api('/me/drive/items/{item-id}/content') .put(stream);

这是无用的.

我从一个对象中获取文件,我使用

I am getting the files from an object, I use

onChangeFilePicker() {
    this.upload(this.filePicker.nativeElement.files)
}

它给了我一个 File 对象数组.

which gives me an array of File objects.

然后我尝试了很多不同的方法,最后一个

Then I tried many different ways, the last one

    private async uploadFile(graphClient: Client, folderItemId: string, file: File) {
      file.arrayBuffer().then((buffer: ArrayBuffer) => {
        let u8Buffer = new Uint8Array(buffer)
        graphClient
          .api(`/me/drive/items/${folderItemId}:/${file.name}:/content`)
          .post(u8Buffer.values())
            .then(response => {
                console.log('ok')
            })
            .catch(error => {
                console.error(error.stack)
            })        
      })
  }

它创建了一个包含两个字节的文件.

which creates a file with two bytes.

你知道如何解决它吗?

我找到了解决方案,它是关于编码和图形客户端的.

I found the solution, it was about encoding and the Graph Client.

我跳过了 Graph 客户端,转而使用纯 Graph API 请求.这需要传递Authentication Token,并且需要将请求的Body 放在一起.虽然我得到了类似的结果,但当我将 ArrayBuffer 编码为 UInt8Array 时,这些结果得到了修复,如下所示:

I skipped the Graph Client and went for pure Graph API requests. This requires to pass the Authentication Token, and requires to put together the Body of the request. Though I had similar results, those got fixed when I encoded the ArrayBuffer as a UInt8Array, like this:

获取身份验证令牌:

  let graphScopes = new MSALAuthenticationProviderOptions(["Files.ReadWrite.All"]);    
  let userAgentApplication = new UserAgentApplication( { auth: this.authConfiguration} )
  let authProvider = new ImplicitMSALAuthenticationProvider(userAgentApplication, graphScopes );
  
  await authProvider.getAccessToken().
  .then(
    token => {
        let headers = new HttpHeaders({
          'Content-Type':'application/json; charset=utf-8',
          'Authorization': `Bearer ${token}`
        })

然后转换数组缓冲区(如以下建议:Angular 5 HttpClient 发布原始二进制数据)

Then to transform the Array Buffer (as suggested at: Angular 5 HttpClient post raw binary data)

      file.arrayBuffer().then( buffer => {            
          let body = new Uint8Array(buffer)
          let uIntBody = body.buffer;
          

最后发出 HttpClient PUT 请求:

and finally making the HttpClient PUT Request:

async experimentHTTPPostFile(parentId: string, file: File) {    
  let graphScopes = new MSALAuthenticationProviderOptions(["Files.ReadWrite.All"]);    
  let userAgentApplication = new UserAgentApplication( { auth: this.authConfiguration} )
  let authProvider = new ImplicitMSALAuthenticationProvider(userAgentApplication, graphScopes );
  
  await authProvider.getAccessToken()
  .then(
    token => {
        let headers = new HttpHeaders({
          'Content-Type':'application/json; charset=utf-8',
          'Authorization': `Bearer ${token}`
        })

        file.arrayBuffer().then( buffer => {            
          let body = new Uint8Array(buffer)
          let uIntBody = body.buffer;
        
          let url = `${this.MS_GRAPH_BASE_URL}/me/drive/items/${parentId}:/${file.name}:/content`
          this.http.put(url, uIntBody, { headers: headers }).toPromise()
          .then(response => {
            console.log(response)
          })
          .catch(error => {
            console.error(error)
          });                
        })            
      }
  ).catch(error => {
      console.error(error)
  })
}

效果很好,我用 PDF、JPEG 和其他二进制文件进行了测试.

It worked perfectly, I tested with PDF, JPEG and other binary files.

我尝试使用 Graph Client graphClient.api(...).put(...) 对缓冲区进行相同的 UInt8 转换,但并没有解决问题.

I tried doing the same UInt8 transformation of the buffer with the Graph Client graphClient.api(...).put(...), and it does not fix the problem.