Как загрузить файлы или изображения на движке 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.

Другие вопросы по тегам