使用AWS S3 Select和适用于Ruby的AWS开发工具包进行编码错误

时间:2018-09-13 18:50:51

标签: aws-sdk-ruby amazon-s3-select

我正在尝试执行以下操作:

  • 从S3(file.csv)下载Athena查询的输出
  • gzip输出并上传到其他S3位置(file.csv.gz
  • 使用Ruby SDK中的S3 Select来查询file.csv.gz的内容

即使file.csv.gz的内容完全不同,我也总是收到以下错误,总是“在字节8192附近”:

Aws::S3::Errors::InvalidTextEncoding (UTF-8 encoding is required. The text encoding error was found near byte 8,192.)

NB:针对相同的未压缩file.csv使用相同的S3 Select查询可以正常工作。我尝试过各种奇怪的事情,但充满了绝望。

复制步骤:

  1. 以文件s3://mybucket/file.csv开头
  2. 使用aws-cli下载:aws s3 cp s3://mybucket/file.csv file.csv
  3. 使用Gzip压缩文件:gzip file.csv
  4. 上传file.csv.gzaws s3 cp file.csv.gz s3://mybucket/file.csv.gz

代码如下:

class RunsS3SelectQueries
  def self.client
    @client ||= Aws::S3::Client.new
  end

  def self.run_query(sql:, bucket:, key:)
    data = ""
    handler = Aws::S3::EventStreams::SelectObjectContentEventStream.new
    handler.on_records_event do |event|
      puts "----records payload:----"
      payload = event.payload.read
      data += payload
    end
    handler.on_stats_event do |event|
       # get :stats event that contains progress information
       puts event.details.inspect
       # => Aws::S3::Types::Stats bytes_scanned=xx, bytes_processed=xx, bytes_returned=xx
    end
    params = {
      bucket: bucket,
      key: key,
      expression_type: "SQL",
      expression: sql,
      input_serialization: {
        csv: { file_header_info: "USE"}
      },
      output_serialization: {
        csv: {}
      },
      event_stream_handler: handler,
    }
    client.select_object_content(params)
    data
  end
end

以下内容收到文本编码错误。

output = RunsS3SelectQueries.run_query(sql: %q{SELECT * FROM S3Object }, bucket: 'mybucket', key: 'file.csv.gz')

但是,针对未压缩的file.csv运行不会:

output = RunsS3SelectQueries.run_query(sql: %q{SELECT * FROM S3Object }, bucket: 'mybucket', key: 'file.csv')

我尝试了文本编码,内容类型元数据,内容编码等的各种组合,似乎找不到任何有效的方法。我认为,它总是会在字节8192上出现错误,这一事实非常奇怪/可疑。

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

您需要指定将输入input_serialization中压缩,否则s3将尝试对gzip标头进行解码,并在字节8192处收到有关其无效utf-8的错误。

类似以下的方法将起作用:

input_serialization: { csv: { file_header_info: "USE"} CompressionType: "GZIP" }