简体   繁体   English

如何在没有base64编码的情况下将blob数据从ruby提交到MySQL

[英]How to submit blob data into MySQL from ruby without base64 encoding

I have searched without much success how to best submit binary data into a MySQL field of type BLOB, without doing a base64 encoding which increases the size of the data.我搜索了如何最好地将二进制数据提交到 BLOB 类型的 MySQL 字段中,但没有进行增加数据大小的 base64 编码,但没有取得多大成功。

So far my Ruby code looks something like this:到目前为止,我的 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)

The issue is that using Base64 encoding/decoding is not very efficient and I was hopping for something a bit cleaner.问题是使用 Base64 编码/解码效率不高,我正在寻找更简洁的东西。

I also tried an alternative using Marhsal (which does not allow me to send the data without a base64 encoding, but is a bit more compact)我还尝试了使用 Marhsal 的替代方法(它不允许我在没有 base64 编码的情况下发送数据,但更紧凑)

 #In the saving function use Marshal.dump() instead of JSON.dump()
 values=Marshal.dump(values)

 #In Retrieve function use Marshal.load() (or Marshal.restore()) instead of JSON.parse(data)
 data=Marshal.load(data)

However, I get some errors (perhaps someone spots what I do wrong, or has some ideas why this occurs):但是,我遇到了一些错误(也许有人发现我做错了什么,或者有一些想法为什么会发生这种情况):

incompatible marshal file format (can't be read) version 4.8 required; 34.92 given

I tried different flavor of this with/without Base64 encoding or decoding or with/without ZLib compression.我尝试了使用/不使用 Base64 编码或解码或使用/不使用 ZLib 压缩的不同风格。 But I seem to consistently get an error.但我似乎一直收到错误。

How would it be possible to send binary data using Ruby and mysql gem, without base64 encoding.在没有 base64 编码的情况下,如何使用 Ruby 和 mysql gem 发送二进制数据。 Or is it simply a requirement to use base64 encoding for sending the data?或者仅仅是要求使用 base64 编码来发送数据?

The issue is that using Base64 encoding/decoding is not very efficient and I was hopping for something a bit cleaner.问题是使用 Base64 编码/解码效率不高,我正在寻找更简洁的东西。

You're using JSON to convert a large hash to a string, then using ZLib compression on binary data, then Base64 encoding the resulting binary data, and you're worried about efficiency... I'm going to assume you mean spatial efficiency rather than temporal efficiency.您正在使用 JSON 将大哈希转换为字符串,然后对二进制数据使用 ZLib 压缩,然后对生成的二进制数据进行 Base64 编码,您担心效率......我假设您指的是空间效率而不是时间效率。

I guess I'm most curious about why you're Base64 encoding in the first place - a BLOB is a binary data format, and provided you pass an array of bytes to ZLib it should inflate it correctly regardless.我想我最想知道为什么你首先使用 Base64 编码——BLOB 是一种二进制数据格式,如果你将一个字节数组传递给 ZLib,它应该无论如何正确地膨胀它。

Have you tried writing binary data directly to the database?您是否尝试过将二进制数据直接写入数据库? What issues did you experience.你遇到了什么问题。

Edit:编辑:

update SomeTable set Data='xڍ ]o 0 K$ k; H Z *XATb U,where id=1' resulted in an error... Obviously this has to do with the binary nature of the data. update SomeTable set Data='xڍ ]o 0 K$ k; H Z *XATb U,where id=1' 导致错误......显然这与二进制有关数据的性质。 This captures the essence of my question.这抓住了我的问题的本质。 Hope you shine some light on this issue.希望你对这个问题有所了解。

You can't just pass the binary string as a query value as you have here - I think you need to use a query with a bind variable.您不能像这里那样将二进制字符串作为查询值传递 - 我认为您需要使用带有绑定变量的查询。

I'm unsure whether the mysql gem you're using supports query bind parameters, but the format of query you'd use is something along the lines of:我不确定您使用的 mysql gem 是否支持查询绑定参数,但您使用的查询格式类似于:

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

this will permit the mysql to properly escape or encapsulate the binary data that is to be inserted into the database table.这将允许 mysql 正确转义或封装要插入到数据库表中的二进制数据。

To sumarize mcfinningan answer.总结 mcfinningan 的答案。 Transmitting the binary data is done via binding a parameter.传输二进制数据是通过绑定参数来完成的。 In ruby this can be done with 'mysql' gem this can be done using prepared statments (cf. MySQL Ruby tutorial )在 ruby​​ 中,这可以使用 'mysql' gem 完成,这可以使用准备好的 statments 完成(参见MySQL Ruby 教程

The code now looks like:代码现在看起来像:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM