Вставка двоичного файла "нераспознаваемый формат" для postresql и рельсов 4

В настоящее время у меня проблема с хранением файлов в виде двоичных blobs на postresql (9.3) с ruby on rails (4.1.1). При открытии файла с сервера постановки/производства, который я сохранил, я получаю

unrecognizable format

что означает, что файл (возможно) поврежден. Я подтвердил, что с textedit, где файл, загруженный с производства, отображает "x89504e470d0a1a0a0000000d494844520000010b000001c00800000000901112f9000000097048597300000c4e00000c4e017f778c2300000c4e017f778c23000003186943435050686f746f736..." (сначала я думал, что это кодировка base64), когда он должен отображать обычный заголовок PNG тестового файла "... PNG... IHDR.. ".

Как ни странно, проблема возникает только в производственной среде (Centos6 + Passenger + NginX), в то время как среда разработки (MacOS) отлично работает. Более того, я не знаю, является ли это проблемой Postgres, так как после того, как я попытаюсь восстановить производственный дамп на моей машине разработки, файлы, которые я загрузил в производство, открылись просто отлично! Вот код, который создает объект data_file (тот, который содержит двоичное содержимое):

def create authorize! :create, :data_file # cancan authorization file = params[:file] @data_file = DataFile.new(name: file.original_filename, size: file.size, contents: file.read, content_type: file.content_type # + some additional params) authorize! :update, @data_file # other cancan authorization if @data_file.save render("data_files/show", formats: :json) else render json: {errors: @data_file.errors}, status: 403 end
end

и вот код, который отображает файл

def show @data_file = DataFile.find(params[:id]) authorize! :show, @data_file send_data @data_file.contents, :disposition => 'attachment', :filename => @data_file.name
end

здесь приведена схема объекта datafile

create_table "data_files", force: true do |t| t.string "name" t.integer "user_id" t.integer "project_id" t.string "size" t.datetime "created_at" t.datetime "updated_at" t.binary "contents" t.integer "content_type" t.string "valid_from" t.string "valid_until" t.datetime "formatted_valid_until" t.datetime "formatted_valid_from"
end

Было бы здорово, если бы кто-то помог мне в этом вопросе. Странно, что программа ведет себя по-разному в средах, которые кажутся одинаковыми.

Заранее спасибо!

1 ответ

Результат, который вы смотрите, представляет собой шестнадцатеричную строку значения типа bytea сгенерированного PostgreSQL 9.0 или выше, что происходит, когда параметр bytea_output установлен в hex.

Приложение SQL, связанное с pre-9.0 libpq, не будет надлежащим образом декодировать это содержимое и в основном сгладить шестнадцатеричную строку дословно, как показано в вопросе. Предположительно, разница между вашей производственной средой и средой dev - это версия libpq.

В качестве обходного пути, до обновления, вы можете заставить bytea_ouput его более старое значение по умолчанию, escape на нескольких возможных уровнях, в удобное для вас время:

  • для всего кластера, настроенного в postgresql.conf
  • для одной базы данных с ALTER DATABASE dbname SET bytea_output to 'escape';
  • для конкретного пользователя: ALTER USER username SET bytea_output to 'escape'; пользователя ALTER USER username SET bytea_output to 'escape';
  • для сеанса SQL (непостоянный): SET bytea_output TO 'escape';

licensed under cc by-sa 3.0 with attribution.