Вопрос или проблема
Не удалось загрузить файлы через Iconik API SignatureDoesNotMatch
Я пытаюсь создать базовую функцию Node.js для загрузки файла в iconik; после выполнения функции я успешно создаю актив, получаю идентификатор хранилища, создаю формат, создаю набор файлов, но затем возникает ошибка при попытке использовать uploadURL
для загрузки самого файла. Я вижу созданный актив в веб-интерфейсе iconik.
const uploadToIconik = async () => {
try {
const createAssetResponse = await axios.post(`${ICONIK_API_URL}/assets/v1/assets/`, {title: fileName}, {headers: headersIconik});
const assetId = createAssetResponse.data.id;
console.log('#########################################################################');
console.log('###########################################################################');
console.log('## 1 из 7: Актив создан:', assetId);
const storageResponse = await axios.get(`${ICONIK_API_URL}/files/v1/storages/matching/FILES/`, {headers: headersIconik});
const storageId = storageResponse.data.id;
console.log('## 2 из 7: Идентификатор хранилища:', storageId);
const formatResponse = await axios.post(`${ICONIK_API_URL}/files/v1/assets/${assetId}/formats/`, {
user_id: userID,
name: "ORIGINAL",
metadata: [{ internet_media_type: "video/mp4" }],
storage_methods: ["GCS"]
}, {
headers: headersIconik
});
const formatId = formatResponse.data.id;
console.log('## 3 из 7: Формат создан:', formatId);
const fileSetResponse = await axios.post(`${ICONIK_API_URL}/files/v1/assets/${assetId}/file_sets/`, {
format_id: formatId,
storage_id: storageId,
base_dir: "/",
name: fileName,
component_ids: []
}, {
headers: headersIconik
});
const fileSetId = fileSetResponse.data.id;
console.log('## 4 из 7: Набор файлов создан:', fileSetId);
const fileCreateResponse = await axios.post(`${ICONIK_API_URL}/files/v1/assets/${assetId}/files/`, {
original_name: fileName,
size: fileSize,
format_id: formatId,
file_set_id: fileSetId,
storage_id: storageId,
type: 'FILE',
metadata: {},
directory_path: ""
}, {
headers: headersIconik
});
const uploadUrl = fileCreateResponse.data.upload_url;
const fileId = fileCreateResponse.data.id;
console.log('## 5 из 7: URL загрузки:', uploadUrl);
// 6. Загрузка файла
//const fileData = fs.readFileSync(filePath);
const fileStream = fs.createReadStream(filePath);
console.log('## 6 из 7: Длина содержимого: '+ fileSize);
await axios.put(uploadUrl, fileStream, {
headers: {
'Content-Type': 'application/octet-stream',
'x-goog-resumable':'start',
'Content-Length':fileSize
}
});
console.log('## 6 из 7: Файл успешно загружен!');
// 7. Завершение задачи
await axios.patch(`${ICONIK_API_URL}/files/v1/assets/${assetId}/files/${fileId}/`, {
status: "CLOSED",
progress_processed: 100
}, {
headers: headersIconik
});
console.log('## 7 из 7: Загрузка завершена.');
} catch (error) {
// await axios.delete(`${ICONIK_API_URL}/files/v1/assets/${assetId}/uploads/`,{
// headers: headersIconik
// });
console.error('Ошибка при загрузке файла:', error.response ? error.response.data : error.message);
}
};
Логи консоли:
src % node iconik.js
1 из 7: Актив создан: fb8bca28-7777-11ef-847c-9a75db8955fe
2 из 7: Идентификатор хранилища: aaba2964-0a29-11ec-99e0-0a580a3c0e44
3 из 7: Формат создан: fc22dfee-7777-11ef-99b2-4219142fab38
4 из 7: Набор файлов создан: fc41c47c-7777-11ef-8c97-2a655031b7bd
5 из 7: URL загрузки: https://storage.googleapis.com/iconik-us-files/a
Шаг 6 завершился неудачей с следующей ошибкой при запуске URL загрузки, предоставленного самим API.
Ошибка загрузки файла: <?xml version='1.0' encoding='UTF-8'?><Error><Code>SignatureDoesNotMatch</Code><Message>Доступ запрещен.</Message><Details>Подпись запроса, которую мы вычислили, не совпадает с предоставленной вами подписью. Проверьте ваш секретный ключ Google и способ подписи.</Details><StringToSign>POST
Любая помощь будет очень приветствоваться. Спасибо всем заранее.
Я пробовал все в соответствии с документацией iconik, но не знаю, нужно ли авторизоваться через OAuth2 или достаточно этого метода, который я пытаюсь использовать, просто с ID приложения и токеном приложения, которые я получил из настроек iconik.
Ответ или решение
Проблема, с которой вы столкнулись, связана с ошибкой SignatureDoesNotMatch
при попытке загрузки файла через API Iconik. Это свидетельствует о несоответствии сигнатуры, связанной с вашим запросом и тем, как Google Cloud Storage ожидает ее. Давайте разберем шаги, которые могут помочь решить эту проблему.
Шаги для устранения проблемы
-
Проверка URL загрузки: Убедитесь, что
uploadUrl
, который вы получаете от API Iconik, корректный и действительно относится к ресурсу Google Cloud Storage. Вы можете скопироватьuploadUrl
и попробовать открыть его в браузере. Если бы он был недоступен, вы бы увидели другую ошибку. -
Параметры заголовков: Убедитесь, что заголовки, которые вы передаете в запросе на загрузку, включают все необходимые атрибты. Похоже, вы передаете только
Content-Type
иx-goog-resumable
. Некоторые API могут требовать дополнительных заголовков, таких какAuthorization
или специальные заголовки, специфичные для Google Cloud Storage. -
Метод аутентификации:
- Если вы используете
APP ID
иAPP TOKEN
, убедитесь, что они правильно настроены для доступа к вашему ресурсу. Иногда может понадобиться использовать OAuth2 для более безопасной аутентификации. - Проверьте, имеете ли вы все необходимые разрешения для записи в указанный bucket в Google Cloud Storage (GCS).
- Если вы используете
- Правильная инициализация запроса:
- Убедитесь, что вы прежде чем пытаться загрузить файл, действительно инициируете загрузку как "resumable". В вашем коде вы не указали
x-goog-resumable: start
в части инициализации. - Убедитесь, что файл, который вы загружаете, действительно доступен и имеет правильный путь.
- Убедитесь, что вы прежде чем пытаться загрузить файл, действительно инициируете загрузку как "resumable". В вашем коде вы не указали
Вот небольшое переосмысление части вашего кода, которое может помочь:
// 6. Upload File
const fileStream = fs.createReadStream(filePath);
console.log('## 6 of 7: Content-Length: ' + fileSize);
// Инициализируем загрузку
await axios.put(uploadUrl, fileStream, {
headers: {
'Content-Type': 'application/octet-stream',
'x-goog-resumable': 'start',
'Content-Length': fileSize,
'Authorization': `Bearer ${process.env.GOOGLE_API_TOKEN}` // Если необходимо
}
});
- Просмотр ответа от GCS: Если ошибка сохраняется, проверьте полное сообщение об ошибке – возможно, есть дополнительные подсказки, указывающие на точную причину проблемы.
Резюме
Следуйте вышеперечисленным шагам, чтобы убедиться, что все параметры и настройки передаются правильно. Если возникнут дополнительные проблемы, проверьте настройки вашего проекта в Google Cloud и убедитесь, что вы используете нужные токены и права доступа. Если требуется, вы можете также изменить способ аутентификации на OAuth2 для обеспечения более безопасного доступа.
Если проблема не решается, будьте готовы предоставить более подробную информацию о ваших настройках API и использовании токенов для дальнейшего анализа.