Как преобразовать bytea Postgres в строку base64

У меня есть изображение base64, которое я пытаюсь сохранить в базе данных Postgres (используя Hasura). Поле имеет тип bytea. Я не знаю, как сохранить эти данные в поле.

Я попытался передать data:image/png;base64,sisodjodo... в поле, и оно сохраняется так: \x6956424f5277304b47676f414141414...

Когда я получаю его обратно, кажется, что он не возвращается таким же образом, как он был сохранен.

// Query the database and save resulting object
const user = {
  avatar: '\x6956424f5277304b47676f414141414...'
}
user.avatar = btoa(user.avatar);
console.log(user.avatar);
// Prints: XHg2OTU2NDI0ZjUyNzczMDRiNDc2NzZmNDE0MTQxNDE0Z...

person Get Off My Lawn    schedule 14.10.2020    source источник
comment
Чем бы ни был btoa(), он не рассматривает ваш '\x6956424f5277304b47676f41414141' как двоичный файл. Вместо этого он обрабатывает его как строковое представление \x6956424f5277304b47676f41414141. Я не делаю javascript, так как это родной язык дьявола, но я смог продублировать ваш вывод, используя select encode('\\x6956424f5277304b47676f41414141', 'base64'); на языке не тьмы.   -  person Mike Organek    schedule 15.10.2020
comment
Используйте text, а не bytea для изображения в кодировке base64.   -  person Laurenz Albe    schedule 15.10.2020
comment
@MikeOrganek btoa() создает строку ASCII в кодировке Base64 из двоичной строки (то есть объекта String, в котором каждый символ в строке обрабатывается как байт двоичных данных).   -  person Get Off My Lawn    schedule 15.10.2020
comment
@LaurenzAlbe Я не уверен, что смогу, я не администратор базы данных, поэтому у меня нет возможности это изменить.   -  person Get Off My Lawn    schedule 15.10.2020
comment
Представление, которое вы видите, представляет собой шестнадцатеричное строковое представление двоичных данных, хранящихся в столбце. Что бы вы ни использовали для извлечения его из базы данных, оно обрабатывается как строка, а не массив байтов. Можете ли вы включить код, который вы используете для запроса PostgreSQL?   -  person Mike Organek    schedule 15.10.2020
comment
Используемый запрос генерируется Hasura, поэтому я предполагаю, что они выбирают его как строку, как вы говорите. Однако я нашел способ сделать столбец текстовым через интерфейс Hasura, как упоминал @LaurenzAlbe.   -  person Get Off My Lawn    schedule 15.10.2020


Ответы (1)


Поля Postgres bytea должны быть введены в одном из двух форматов, самый простой из которых — шестнадцатеричный. Этот формат выглядит как \x[your byte string in hex]

Итак, предположим, что у вас есть таблица с именем things со столбцом bytea field, вы можете вставить новую строку со строкой байтов 010101 следующим образом:

mutation {
  insert_things_one(object: {
    field: "\\x010101"
  }) {
    field
  }
}

Результат будет:

{
  "data": {
    "insert_thing_one": {
      "field": "\\x010101"
    }
  }
}

Обратите внимание, что в GraphQL вам нужно избегать \. Вы можете проверить в SQL, что он сохранен правильно:

> select * from things;

field
\x010101

Если вы хотите сохранить строку байтов в кодировке base64 для вашего вопроса, вам нужно удалить начальный data:image/png;base64,, а затем закодировать строку base64 в шестнадцатеричном формате на любом языке, который вы используете. В JS: декодировать Base64 в шестнадцатеричную строку с помощью javascript


PS. Я бы не рекомендовал использовать текстовые поля для хранения строк в кодировке base64. Это будет стоить вам намного больше места для хранения, чем необходимо. Просто перекодируйте в шестнадцатеричный код, согласно моему ответу выше.

person Dmitry Minkovsky    schedule 17.10.2020
comment
Хорошо здорово! Сейчас он сохраняется, но как мне преобразовать его обратно в base64 при выполнении запроса с Hasura? - person Get Off My Lawn; 20.10.2020
comment
НВМ: btoa(user.avatar.replace('\\x', '').match(/\w{2}/g).map(a => String.fromCharCode(parseInt(a, 16))).join("")) - person Get Off My Lawn; 20.10.2020
comment
Ага, точно! ???? - person Dmitry Minkovsky; 21.10.2020