Как загрузить файлы или изображения на движке hasura graphql
Пример:
- загрузить файл на сервер и сохранить полученный путь к базе данных, только авторизованные пользователи должны иметь возможность загружать файлы
Как это реализовать?
2 ответа
Подводя итог у нас есть 3 способа:
- клиент загружает на s3 (или подобный сервис), получает URL-адрес файла, затем выполняет мутацию вставки / обновления в нужную таблицу
- Custom Uploader - написать приложение / сервер, который загружает файлы и изменяет БД и использует маршрутизацию nginx для перенаправления некоторых запросов к нему
- пользовательский распознаватель с использованием схемы сшивания ( пример)
Если вы загружаете файлы в AWS S3, существует простой способ, при котором вам не нужно запускать другой сервер для обработки загрузки файлов или создавать обработчик для действия hasura.
В основном, когда вы загружаете файлы на S3, лучше получить подписанный URL-адрес из бэкэнда и напрямую загрузить на s3. Кстати, для хостинга с несколькими размерами изображений этот подход прост и безболезнен.
Важнейшим моментом является получение подписанного URL-адреса s3 для загрузки.
В node.js вы можете сделать
const AWS = require("aws-sdk");
const s3 = new AWS.S3({ apiVersion: "2006-03-01" });
const signedUrl = s3.getSignedUrl("putObject", {
Bucket: "my-bucket",
Key: "path/to/file.jpg",
Expires: 600,
});
console.log("signedUrl", signedUrl);
Пример signedUrl похож на
https://my-bucket.s3.amazonaws.com/path/to/file.jpg?AWSAccessKeyId=AKISE362FGWH263SG&Expires=1621134177&Signature=oa%2FeRF36DSfgYwFdC%2BRVrs3sAnGA%3D
.
Обычно вы помещаете приведенный выше код в обработчик, размещенный в AWS Lambda или сбой, и добавляете некоторую логику для авторизации и даже добавляете строку в таблицу.
Как видите, самая важная часть - это
Signature=oa%2FeRF36DSfgYwFdC%2BRVrs3sAnGA%3D
. Как мы можем упростить получение подписи?
Покопавшись в AWS JS SDK, мы можем найти здесь вычисленную подпись .
return util.crypto.lib.createHmac(fn, key).update(string).digest(digest);
fn = 'sha1'
string = 'PUT\n\n\n1621135558\b/my-bucket/path/to/file.jpg'
digest = 'base64'
Это просто sha1 определенный формат строки. Это означает, что мы можем просто использовать вычисляемые поля hasura и криптографическую функцию Postgres для достижения тех же результатов.
Так что если у вас есть таблица "файлы"
CREATE TABLE files (
id SERIAL,
created_at timestamps,
filename text,
user_id integer
);
вы можете создать функцию SQL
CREATE OR REPLACE FUNCTION public.file_signed_url(file_row files)
RETURNS text
LANGUAGE sql
STABLE
AS $function$
SELECT ENCODE( HMAC(
'PUT' ||E'\n'||E'\n'||E'\n'||
(cast(extract(epoch from file_row.created_at) as integer) + 600)
||E'\n'|| '/my-bucket/' || file_row.filename
, 'AWS_SECRET', 'SHA1'), 'BASE64')
$function$
Наконец, выполните следующие действия, чтобы открыть это вычисленное поле Хасуре.
Таким образом вы сможете не добавлять никаких бэкэнд-материалов и обрабатывать разрешения полностью в Hasura.