Reputation: 11
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,
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);
which is useless.
I am getting the files from an object, I use
onChangeFilePicker() {
this.upload(this.filePicker.nativeElement.files)
}
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.
Do you have any idea on how to solve it?
Upvotes: 1
Views: 1824
Reputation: 11
I found the solution, it was about encoding and the Graph Client.
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:
To get the Authentication Token:
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}`
})
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;
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)
})
}
It worked perfectly, I tested with PDF, JPEG and other binary files.
I tried doing the same UInt8 transformation of the buffer with the Graph Client graphClient.api(...).put(...), and it does not fix the problem.
Upvotes: 0