3 дня работаю над этой простой штукой, нужен мудрый совет:
Мне нужно отправить файл в общую папку OneDrive другого пользователя из Node.js.
-
В Azure я убедился, что у меня есть соответствующие разрешения: Files.ReadWrite.All типа Application Files.ReadWrite.All типа Delegated
-
Также я добавил необязательные утверждения: act — статус учетной записи пользователя в тенанте — тип токена: Access
Затем я получаю токен доступа, вызывая MSAL ConfidentialClientApplication, а затем приобретаюTokenByClientCredential, например:
function generateTokenPromise() {
let config = {
auth: {
clientId: applicationId,
authority: msOnlineBaseUrl + '/' + tenantId,
clientSecret: clientSecretValue,
},
system: {
loggerOptions: {
loggerCallback(loglevel, message, containsPii) {
console.log(message);
},
piiLoggingEnabled: false,
logLevel: msal.LogLevel.Verbose,
}
}
};
// Create msal application object
let cca = new msal.ConfidentialClientApplication(config);
let clientCredentialRequest = {
tenant: tenantId,
client_id: applicationId,
scopes: ["https://graph.microsoft.com/.default"],
client_secret: clientSecretValue,
azureRegion: "centralus",
skipCache: true,
grant_type: "client_credentials",
};
return cca.acquireTokenByClientCredential(clientCredentialRequest)
}
Токен хороший, он позволяет мне работать с учетной записью другого пользователя:
- Я могу читать содержимое корневой и дочерней папок.
- Я могу читать информацию об элементах диска, как о файлах, так и о папках.
- Я могу создать папку в другой учетной записи.
Но когда я пытаюсь создать файл, приложение выдает мне код ошибки HTTP 401: Неавторизованный ответ об ошибке клиента. Что не имеет смысла. У меня правильная аутентификация, токен хороший, иначе он не позволял бы выполнять другие функции.
Чтобы создать запрос, я использую Node.js FormData с буфером. Я урезал код, пытаясь заставить его работать:
function uploadBinaryFile(req, res) {
let token
generateTokenPromise()
.then(tokenResponse => {
// token = tokenResponse.accessToken
return receiveBinaryFilePromise(req)
})
.then(async buffer => {
let microsoftUserId = 'LidiaH@appsname.onmicrosoft.com'
let foundFolderName = 'found-folder'
let foundFolderId = '01S2X...TOETQ' // this is the found-folder's Folder Id
let filename = "new-file.jpg"
let url = new URL(`/users/${microsoftUserId}/drive/items/${foundFolderId}:/${filename}:/content`, msGraphBaseUrl)
// let url = new URL(`/users/${microsoftUserId}/drive/root:/${foundFolderName}/${filename}:/content`, msGraphBaseUrl)
let form = new FormData()
// form.append('uploadFile', buffer)
form.append('field', 'a,b,c', 'blah.csv'); // TODO: this is a test, use the buffer later
let headersConfig = {
"Authorization": `Bearer ${token}`,
...form.getHeaders()
}
return axios({
method: 'post',
url: url.toString(),
data: form,
headers: headersConfig
})
})
.then(thing => {
console.log('Success!')
})
.catch(error => {
console.error(error)
})
}
Я с подозрением отношусь к тому, что делает axios для запуска запроса. Я пытался изменить headerConfig и URL-адрес, но у меня заканчиваются идеи и время.
Я также читал о FormData, но думаю, что это хорошо.
Вы знаете, как это сделать? Можете предложить статью? Работа вокруг? Некий путеводный свет в конце туннеля?
Спасибо Луис.
Вы используете
POST
, в то время как документация предлагает использоватьPUT
. Вы когда-нибудь пытались загрузить файл через Postman?@MarioVarchmin, ты был совершенно прав. Я изменил его на PUT, а затем попробовал в Postman. Добавил файл в Тело как Бинарный файл, потом попробовал, после исправления запроса заработало! Благодарю вас!
Я рад слышать, что теперь это работает на вас.
Здравствуйте @MarioVarchmin, не могли бы вы опубликовать свое предложение в качестве ответа, поскольку оно сработало для DigitalOnion и поможет другим членам сообщества.
@ansumanBal-MT: Готово!
@MarioVarchmin, спасибо!