Ошибка кодирования при использовании AWS S3 Select с AWS SDK для Ruby - PullRequest
0 голосов
/ 13 сентября 2018

Я пытаюсь сделать следующее:

  • загрузить выходные данные запроса Athena из S3 (file.csv)
  • сжать выходные данные и загрузить их в другое местоположение S3(file.csv.gz)
  • используйте S3 Выберите из Ruby SDK для запроса содержимого file.csv.gz

Я всегда получаю следующую ошибку, всегда "рядом с байтом 8192",даже когда содержимое file.csv.gz полностью отличается:

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

Примечание: использование одного и того же запроса S3 Select для одного и того же несжатого file.csv работает, как и ожидалось.Я перепробовал разные странные вещи, но полон отчаяния.

Шаги для воспроизведения:

  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.gz: aws 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 голосов
/ 04 января 2019

Вы должны указать, что входные данные сжаты в input_serialization, иначе s3 попытается декодировать заголовок gzip и получит сообщение об ошибке, что он недействителен utf-8 в байте 8192.

Будет работать что-то вроде следующего:

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

...