Вложение двоичного файла "до неузнаваемости" для postresql и rails 4
В настоящее время у меня есть проблема с хранением файлов в виде двоичных объектов на postresql (9.3) с ruby на rails (4.1.1). При открытии файла с промежуточного / рабочего сервера, который я сохранил, я получаю
unrecognizable format
Это означает, что файл (вероятно) поврежден. Я подтвердил это с помощью textedit, где загруженный с производства файл отображает "x89504e470d0a1a0a0000000d494844520000010b000001c00800000000901112f9000000097048597300000c4e00000c4e017f778c00000c4e017f778c00000c4e017f778c00000c4e017f778c00000000097048597300000c4e00000c4e017f778c2300000318694... в коде H150...".
Как ни странно, проблема возникает только в производственной среде (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, связанное с пре-9.0 libpq
не будет должным образом декодировать это содержимое и в основном извергать дословно шестнадцатеричную строку, как показано в вопросе. Предположительно, разница между вашей производственной средой и средой разработки заключается в версии libpq
,
В качестве обходного пути, до обновления, вы можете заставить bytea_ouput
к его старому значению по умолчанию, escape
на нескольких возможных уровнях:
- для всего кластера, настроенного в
postgresql.conf
- для одной базы данных с
ALTER DATABASE dbname SET bytea_output to 'escape';
- для конкретного пользователя:
ALTER USER username SET bytea_output to 'escape';
- для сеанса SQL (непостоянный):
SET bytea_output TO 'escape';