#javascript #node.js #azure-data-lake-gen2
#javascript #node.js #azure-data-lake-gen2
Вопрос:
Я пытаюсь создать подпись общего доступа на стороне клиента в моем приложении узла. Причина в том, что я не хочу передавать файлы через свое приложение. Я хочу, чтобы пользователь мог напрямую загружать файл в мой контейнер для хранения больших двоичных объектов Azure Data Lake Gen2.
Я просмотрел все примеры, которые смог найти, но все они на стороне сервера. Итак, я попытался сгенерировать параметры generateDataLakeSASQueryParameters и использовать их в запросе ВВОДА. Процесс выглядит так, как будто он работает, и я возвращаю его клиенту.
На стороне сервера:
async getFileUploadUrl(path) {
const now = new Date().toUTCString();
const startsOn = new Date(now);
startsOn.setMinutes(startsOn.getMinutes() - 10); // Skip clock skew with server
const expiresOn = new Date(now);
expiresOn.setHours(expiresOn.getHours() 1); // Expires in one hour
const sharedKeyCredential = new StorageSharedKeyCredential(this.storageAccountName, this.accountKey);
const sas = generateDataLakeSASQueryParameters({
fileSystemName: this.fileSystemClient.name,
ipRange: { start: "0.0.0.0", end: "255.255.255.255" },
expiresOn,
protocol: SASProtocol.HttpsAndHttp,
permissions: DataLakeSASPermissions.parse("c").toString(), // Read (r), Write (w), Delete (d), List (l), Add (a), Create (c), Update (u), Process (p)
resourceTypes: AccountSASResourceTypes.parse("o").toString(), // Service (s), Container (c), Object (o)
services: AccountSASServices.parse("b").toString(), // Blob (b), Table (t), Queue (q), File (f)
startsOn,
version: "2019-12-12"
},
sharedKeyCredential);
const encodedURI = encodeURI(path);
const filePath = `${this.fileSystemClient.url}/${encodedURI}`;
return {
url: filePath,
signature: sas.signature,
};
}
На стороне клиента:
const { url, signature } = serverResponse;
const file = [file takes from an input tag];
const request = new XMLHttpRequest();
request.open('PUT', url, true);
request.setRequestHeader("x-ms-date", new Date().toUTCString());
request.setRequestHeader("x-ms-version", '2019-12-12');
request.setRequestHeader("x-ms-blob-type", 'BlockBlob');
request.setRequestHeader("Authorization", `SharedKey [storageaccount]:${signature}`);
request.send(file);
И то, что я продолжаю получать, — это 403 со следующей ошибкой:
Подпись MAC, найденная в HTTP-запросе ‘[signature]’, не совпадает с любой вычисленной подписью. Сервер использовал следующую строку для подписи: ‘PUT n n n n1762213n n n n n n n n n n n nx-ms-дата:Чт, 24 Сен 2020 12:24:05 GMT nx-ms-версия:2019-12-12n/[имя учетной записи]/ [имя контейнера]/ [имя папки]/image.png’.
Очевидно, я удалил фактическую подпись, поскольку я заставил ее работать на стороне сервера, но она выглядит примерно так: hGhg765 nigjhgluhuuuyg686dnh90hkyfytf6= (Я это придумал, но похоже, что она в правильном формате).
Я также пытался вернуть проанализированную строку запроса и использовать ее в запросе PUT, но затем я получаю ошибки, указывающие, что отсутствует требуемый заголовок, и я не могу понять, какой из них должен быть. Authorization
Например, не требуется.
Ответ №1:
Этот метод generateDataLakeSASQueryParameters
используется для создания токена службы sas. После этого мы можем вызвать Azure Datalake Rest API с токеном sas в качестве параметра запроса
Например
- Создайте токен sas с помощью метода
generateDataLakeSASQueryParameters
. Когда мы вызываем методgenerateDataLakeSASQueryParameters
, мы должны определитьDataLakeSASSignatureValues
класс: https://learn.microsoft.com/en-us/javascript/api/@azure/storage-file-datalake/datalakesassignaturevalues?view=azure-node-latest
const {
StorageSharedKeyCredential,
generateDataLakeSASQueryParameters,
DataLakeSASPermissions,
} = require("@azure/storage-file-datalake");
const accountName = "testadls05";
const accountKey ="";
const now = new Date().toUTCString();
const startsOn = new Date(now);
startsOn.setMinutes(startsOn.getMinutes() - 10); // Skip clock skew with server
const expiresOn = new Date(now);
expiresOn.setHours(expiresOn.getHours() 1); // Expires in one hour
const fileSas = generateDataLakeSASQueryParameters(
{
fileSystemName: "test",
pathName: "test.jpg",
permissions: DataLakeSASPermissions.parse("racwd"),
startsOn: startsOn,
expiresOn: expiresOn,
},
new StorageSharedKeyCredential(accountName, accountKey)
).toString();
console.log(fileSas);
- Тест (создать файл)
PUT http:// https://{accountName}.{dnsSuffix}/{filesystem}/{path}
?{sas token you create in step1}
Headers:
Content-Type:image/jpeg
Content-Length:0
Комментарии:
1. Внес предложенные изменения, все равно получите это в ответе:
MissingRequiredHeader: An HTTP header that's mandatory for this request is not specified.
2. @Vhendin Пожалуйста, обратитесь к learn.microsoft.com/en-us/rest/api/storageservices /… чтобы определить ваш api.
3. @JimXu, спасибо!! Я потратил часы, просматривая документы, пытаясь разобраться в этом. Для меня все работало отлично