某Webアプリ、スマホアプリ開発の企業に勤めているエンジニアの日記です。主に、技術系記事や本の要約を発信します。

null byteエラーが発生したときの対処

やりたいこと

①S3から複数のZipファイルを取得

②複数のzipファイルを解凍しディレクトリ形式にする

③最終的に1つのzipファイルにしたい。

起きた問題

①でget_objectしたところ、以下のようになってしまい、②で必要なファイルパスが取得できない状況。

PK\u0003\u0004\u0014\u0000\u0000\u0000\u0000\u0000\xA1\x9AYQ\u0000\u0000\u0000

client = Aws::S3::Client.new(
    :region => 'ap-northeast-1',
    :access_key_id => '***',
    :secret_access_key => '***',
)      
@orders.each do |order|
    obj = client.get_object(
    bucket: "*",
    key: order.zip_file_name
    ).body.read  
    
    Rails.logger.debug obj.inspect
    #=> PK\u0003\u0004\u0014\u0000\u00....
end

原因

zipファイルの中身はバイナリデータ。

ダウンロードしてきたファイルの中身をobjに参照させている。.body.readという関数は、zipファイルの中身を参照する関数。なので、当然バイナリがログで出てくる。

解決策

readせずに、rubyzipのopen_bufferメソッドを使って、zipファイルを開く。 ただ、open_bufferメソッドはrubyzipの公式ドキュメントには載っていない。。。 もっと良いやり方見つけたい。

client = Aws::S3::Client.new(
    :region => 'ap-northeast-1',
    :access_key_id => '***',
    :secret_access_key => '***',
)      
@orders.each do |order|
    obj = client.get_object(
    bucket: "*",
    key: order.zip_file_name
    ).body  >> readしない!    
end

## get_objectでopenする
Zip::File.open_buffer(obj) do |zip|
    ~~
end