如何在不使用base64编码的情况下从ruby向MySQL提交blob数据

如何在不使用base64编码的情况下从ruby向MySQL提交blob数据,mysql,ruby,Mysql,Ruby,我已经搜索了如何最好地将二进制数据提交到BLOB类型的MySQL字段中,而没有进行base64编码(这会增加数据的大小),但没有获得多少成功 到目前为止,我的Ruby代码如下所示: require 'zlib' require 'base64' require 'mysql' #Initialization of connection function db = Mysql.init db.options(Mysql::OPT_COMPRESS, true) db.options(

我已经搜索了如何最好地将二进制数据提交到BLOB类型的MySQL字段中,而没有进行base64编码(这会增加数据的大小),但没有获得多少成功

到目前为止,我的Ruby代码如下所示:

require 'zlib'
require 'base64'
require 'mysql'

#Initialization of connection function
  db = Mysql.init
  db.options(Mysql::OPT_COMPRESS, true)
  db.options(Mysql::SET_CHARSET_NAME, 'utf8')
  dbh = db.real_connect('hostname','username','password','database') #replace with appropriate connection details

#Saving the data function
  values=someVeryBigHash
  values=JSON.dump(values)
  values=Zlib::Deflate.deflate(values, Zlib::BEST_COMPRESSION)
  values=Base64.encode64(values)
  dbh.query("update `SomeTable` set Data='#{values}' where id=1")
  dbh.close if dbh

#Retrieving the data function
  res=dbh.query("select * from `SomeTable` where id=1")
  data=res['Data']
  data=Base64.decode64(data)
  data=Zlib::inflate(data)
  data=JSON.parse(data)
问题是使用Base64编码/解码不是很有效,我正在寻找更干净的东西

我还尝试了另一种使用Marhsal的方法(它不允许我在没有base64编码的情况下发送数据,但更紧凑一些)

但是,我会犯一些错误(可能有人发现我做错了什么,或者有人知道为什么会发生这种情况):

我尝试了不同的风格,使用/不使用Base64编码或解码,或者使用/不使用ZLib压缩。但我似乎总是犯错误

在没有base64编码的情况下,如何使用Ruby和mysql gem发送二进制数据。还是仅仅要求使用base64编码来发送数据

问题是使用Base64编码/解码不是很有效,我正在寻找更干净的东西

您使用JSON将一个大哈希转换为字符串,然后对二进制数据使用ZLib压缩,然后对生成的二进制数据进行Base64编码,您担心效率。。。我假设你指的是空间效率而不是时间效率

我想我最好奇的是为什么首先使用Base64编码——BLOB是一种二进制数据格式,如果你将一个字节数组传递给ZLib,它应该正确地膨胀

您是否尝试过将二进制数据直接写入数据库?你遇到了什么问题

编辑:

更新SomeTable set Data='xڍ�]o�0��K$�K�H��Z�*XATb�U、 其中id=1'导致错误。。。显然,这与数据的二进制性质有关。这抓住了我问题的本质。希望你能对这个问题有所启发

您不能像这里那样将二进制字符串作为查询值传递-我认为您需要使用带有绑定变量的查询

我不确定您使用的mysql gem是否支持查询绑定参数,但您使用的查询格式大致如下:

@db.execute('update SomeTable set Data=? where id = 1', <binary data value>) 
@db.execute('updatesometable set Data=?where id=1',)

这将允许mysql正确地转义或封装要插入到数据库表中的二进制数据。

总结mcfinningan的答案。传输二进制数据是通过绑定一个参数来完成的。在ruby中,这可以通过“mysql”gem来完成,这可以通过使用准备好的语句来完成(参见)

代码现在看起来像:

require 'zlib'
require 'mysql'

#Initialization of connection function
  db = Mysql.init
  db.options(Mysql::OPT_COMPRESS, true)
  db.options(Mysql::SET_CHARSET_NAME, 'utf8')
  dbh = db.real_connect('hostname','username','password','database') #replace with appropriate connection details

#Saving the data function (can skip Zlib compression if needed)
  values=someVeryBigHash
  values=Marshal.dump(values)
  values=Zlib::Deflate.deflate(values, Zlib::BEST_COMPRESSION)

  #Here is how to load the binary data into MySQL (assumes your schema has some tale with a Column Data of type BLOB
  dbh.prepare("update `SomeTable` set Data=? where id=1")
  dbh.execute(data)
  #End of Data loading

  dbh.close if dbh


#Retrieving the data function (can skip Zlib decompression if data is not compressed)
  res=dbh.query("select * from `SomeTable` where id=1")
  data=res['Data']
  data=Zlib::inflate(data)
  data=Marshal.restore(data)

谢谢你的及时答复。是的,我最担心的是空间信息和数据库开销(即代码运行在具有数千个内核的集群上)。我希望能够以二进制格式将数据直接提交到数据库,但当我这样做时,我会遇到一些错误。在这里发布错误-最好解决根本问题,而不是解决它,正如您所说,这里的Base64编码是一种非常好的解决方法。update
SomeTable
set data='xڍ�]o�0��K$�K�H��Z�*XATb�U、 其中id=1'导致错误。。。显然,这与数据的二进制性质有关。这抓住了我问题的本质。希望您能对这个问题有所了解。'Error#:1064'消息:“您的SQL语法有错误;请查看与MySQL服务器版本对应的手册,以了解使用“g”附近的正确语法��#�>�"0��dx��B�Tq�^�#��(K)���>�(d)�' 其中id=1'在第1行',这似乎是因为一些二进制代码转换为“'”(引号),这打破了SQL语法。无论如何,我不知道如何使用mysql ruby gem发送文本变量的二进制内容。
@db.execute('update SomeTable set Data=? where id = 1', <binary data value>) 
require 'zlib'
require 'mysql'

#Initialization of connection function
  db = Mysql.init
  db.options(Mysql::OPT_COMPRESS, true)
  db.options(Mysql::SET_CHARSET_NAME, 'utf8')
  dbh = db.real_connect('hostname','username','password','database') #replace with appropriate connection details

#Saving the data function (can skip Zlib compression if needed)
  values=someVeryBigHash
  values=Marshal.dump(values)
  values=Zlib::Deflate.deflate(values, Zlib::BEST_COMPRESSION)

  #Here is how to load the binary data into MySQL (assumes your schema has some tale with a Column Data of type BLOB
  dbh.prepare("update `SomeTable` set Data=? where id=1")
  dbh.execute(data)
  #End of Data loading

  dbh.close if dbh


#Retrieving the data function (can skip Zlib decompression if data is not compressed)
  res=dbh.query("select * from `SomeTable` where id=1")
  data=res['Data']
  data=Zlib::inflate(data)
  data=Marshal.restore(data)