我目前在使用ruby on rails(4.1.1)在postresql(9.3)上将文件存储为二进制blob时遇到问题。从我保存的登台/生产服务器打开文件时,我得到了
unrecognizable format
表示文件(可能)已损坏。我确认使用textedit,从生产中下载的文件显示" x89504e470d0a1a0a0000000d494844520000010b000001c00800000000901112f9000000097048597300000c4e00000c4e017f778c23000003186943435050686f746f736 ..." (首先我认为它是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
这是数据文件对象的模式
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
如果有人可以帮我解决这个问题,那将会很棒。奇怪的是,程序在看似相同的环境中表现不同。
提前谢谢!
答案 0 :(得分:3)
您正在查看的结果是由PostgreSQL 9.0或更高版本生成的类型为bytea
的值的十六进制字符串,当bytea_output
参数设置为hex
时会发生这种情况。
与9.0之前的libpq
链接的SQL应用程序将无法正确解码这些内容,并且基本上会像问题中所示那样逐字回流十六进制字符串。据推测,您的生产环境和开发环境之间的差异是libpq
的版本。
作为一种解决方法,在升级之前,您可以在方便的时候在几个可能的级别强制bytea_ouput
使用其旧的默认值escape
:
postgresql.conf
ALTER DATABASE dbname SET bytea_output to 'escape';
ALTER USER username SET bytea_output to 'escape';
SET bytea_output TO 'escape';