質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

2回答

5553閲覧

[Ruby On Rails]rubyzipでzipファイルを解凍すると文字化けしてフォルダの順番を保持できない

s_diff

総合スコア107

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

1クリップ

投稿2018/12/21 09:43

編集2022/01/12 10:55

フォームでzipファイルを入れて送信するとコントローラで解凍し、中に入っていたファイルをproducts_image1 ~ products_image30カラムに格納する機能を作っています。

##環境
macOS High Sierra(バージョン10.13.6)
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin17]
Rails 4.2.6
rubyzip (1.2.2)

##試したこと

zipファイル内にはフォルダが5つあり、それぞれフォルダ名を「1」「2」「3」「4」「5」にしています。理由は、このフォルダの番号順にレコードを作成したいからです。
ちなみにフォルダ1に入っているファイルは1つ、フォルダ2に入っているファイルも1つ、フォルダ3からフォルダ5までに入っているファイルは複数あります。

ruby

1def create 2 @product = Product.new(product_params) 3 p "1111111111111111111111111111111" 4 p product_params[:zip] 5 p "1111111111111111111111111111111" 6 7 Zip.unicode_names = true 8 Zip.force_entry_names_encoding = 'UTF-8' 9 10 zipfile = product_params[:zip] 11 Zip::File.open(zipfile.path) do |zip| 12 num = 0 13 zip.each do |entry| 14 entry.name.force_encoding('UTF-8') 15 entry_name = entry.name.encode("UTF-16BE", "UTF-8", :invalid => :replace, :undef => :replace, :replace => '?').encode("UTF-8") 16 p "aaaaaaaaaaaaaaaaaaaaaaaaaaa" 17 p entry_name 18 p "aaaaaaaaaaaaaaaaaaaaaaaaaaa" 19 ext = File.extname(entry_name) #拡張子を取得 20 # 隠しファイルやゴミファイルは飛ばす 21 next if ext.blank? || File.basename(entry_name).count(".") > 1 22 23 num += 1 24 if num > 30 then 25 break 26 end 27 28 # 一時ファイルを作る 29 Tempfile.open(["tempProductImageFile", ext]) do |t| 30 entry.extract(t.path) { true } 31 @product.send("products_image#{num}=", t) 32 end 33 end 34 end 35 end

以上のコードを実行して、実際に画像ファイルを見ると、zipファイルを作った時の順番ではありませんでした。
rails s でログを見てみると、

"1111111111111111111111111111111" #<ActionDispatch::Http::UploadedFile:0x007fbfa9b5e440 @tempfile=#<Tempfile:/var/folders/zx/41df886555n2m1gp6mqb0kkh0000gn/T/RackMultipart20181221-75747-1in4i5x.zip>, @original_filename="images.zip", @content_type="application/zip", @headers="Content-Disposition: form-data; name=\"product[zip]\"; filename=\"images.zip\"\r\nContent-Type: application/zip\r\n"> "1111111111111111111111111111111" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/1/?n?C?g???W?????[_ _?O??-2.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/1/" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_????@?u??.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[__?S?~?u??.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_?u???[?J?[.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_?C???^?[?z???????R??.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_?①?ɒu??.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_?K?X?x???.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_?R?????u??.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_?V???N.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_????.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_?G?A?R???????R??.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_???ʑ?.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[__???ԏ?.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/?n?C?g???W?????[_ 203_?G?A?R??.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/4/" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_???t?g-1.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?m??-4.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_???t?g-2.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?m??-5.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?m??-1.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?L?b?`??.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?C???^?[?z??(????).jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?m??-2.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?m??-3.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_???փh?A.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?o???R?j?[-1.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?o???R?j?[-2.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?N???[?[?b?g.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?C??.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_????.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/?n?C?g???W?????[_ 203_?g?C??.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/3/" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaa" "images/2/?n?C?g???W?????[_-203_?Ԏ??}.jpg" "aaaaaaaaaaaaaaaaaaaaaaaaaaa"

*このアクション自体は成功しますが、意図した順番とはちがいます。

##問題点

  1. UTF-8にするコードを書いているが文字化けしている
  2. 呼び出される順番がimages/1のファイル → images/1 → images/4のファイル → images/4 といったように、意図した順番にならない
  3. images/5もimages/5内にあるファイルも呼ばれていない(実際には格納されている)

何が原因なのかわかりません。そもそもzipファイル内のファイルを意図した順番で並べることが不可能なのでしょうか?
なにかご教示いただけることがあれば、何卒よろしくお願いいたします。

##追記
zip.each do |entry|の中でencodingのコードを追加しましたが、問題点に変化がありません。

ruby

1 Zip::File.open(zipfile.path) do |zip| 2 num = 0 3 zip.each do |entry| 4 unless entry.name.valid_encoding? 5 entry.name.force_encoding case NKF.guess(entry.name) 6 when NKF::EUC then 'euc-jp' 7 when NKF::SJIS then 'cp932' 8 when NKF::UTF8 then 'utf-8' 9 when NKF::UTF16 then 'utf-16' 10 when Encoding::EUCJP_MS then Encoding::EUCJP_MS 11 when Encoding::CP51932 then Encoding::CP51932 12 when Encoding::WINDOWS_31J then Encoding::WINDOWS_31J 13 else 14 # JISコードもしくは不明 15 raise "文字コードが想定外です" 16 end 17 entry.name.encode! 'utf-8' 18 end 19 ext = File.extname(entry.name) #拡張子を取得 20 # 隠しファイルやゴミファイルは飛ばす 21 next if ext.blank? || File.basename(entry.name).count(".") > 1 22 23 num += 1 24 if num > 30 then 25 break 26 end 27 28 # 一時ファイルを作る 29 Tempfile.open(["tempProductImageFile", ext]) do |t| 30 entry.extract(t.path) { true } 31 @product.send("products_image#{num}=", t) 32 end 33 end 34 end

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dice142

2018/12/21 10:10

動作環境を追記していただけますか?
s_diff

2018/12/21 10:18

わかりました。 ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin17] Rails 4.2.6 rubyzip (1.2.2) 以上が動作環境です。
dice142

2018/12/21 10:23

文字コードが関係しているのでOS情報もお願いします。 また、質問文に追記して頂けた方が他の方も見やすいです。
s_diff

2018/12/21 10:24

ご指摘ありがとうございます。
guest

回答2

0

非常に面倒くさいことになってる予感がします・・・

Zip.unicode_names = trueは、(主に)圧縮時のオプションです
Zip.force_entry_names_encoding = 'UTF-8'

rb

1entry.name.force_encoding('UTF-8')

と全く同じ効果しかありません。

なので、unpack時にutf-8でない場合は自分で文字コードを推定する必要があります。

NKF.guesscharlock_holmesを用いる方法があります。

rb

1# NKFを用いた場合 2require 'nkf' 3 4 5unless entry.name.valid_encoding? 6 entry.name.force_encoding case NKF.guess(entry.name) 7 when NKF::EUC then 'euc-jp' 8 when NKF::SJIS then 'cp932' 9 when NKF::UTF8 then 'utf-8' 10 when NKF::UTF16 then 'utf-16' 11 when Encoding::EUCJP_MS then Encoding::EUCJP_MS 12 when Encoding::CP51932 then Encoding::CP51932 13 when Encoding::WINDOWS_31J then Encoding::WINDOWS_31J 14 else 15 # JISコードもしくは不明 16 raise "文字コードが想定外です" 17 end 18 entry.name.encode! 'utf-8' 19end

投稿2018/12/21 10:11

編集2018/12/21 11:12
asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

s_diff

2018/12/21 10:36

ご教示ありがとうございます。 ご指摘を受け、以下のように実装しなおしたところ、entry.name.force_encodingの部分でwrong number of arguments (given 0, expected 1)エラーがでました。 Zip::File.open(zipfile.path) do |zip| num = 0 zip.each do |entry| # entry.name.force_encoding('UTF-8') # entry_name = entry.name.encode("UTF-16BE", "UTF-8", :invalid => :replace, :undef => :replace, :replace => '?').encode("UTF-8") unless entry.name.valid_encoding? entry.name.force_encoding case NKF.guess when NKF::EUC then 'euc-jp' when NKF::SJIS then 'cp932' when NKF::UTF8 then 'utf-8' when NKF::UTF16 then 'utf-16' when Encoding::EUCJP_MS then Encoding::EUCJP_MS when Encoding::CP51932 then Encoding::CP51932 when Encoding::WINDOWS_31J then Encoding::WINDOWS_31J else # JISコードもしくは不明 raise "文字コードが想定外です" end entry.name.encode! 'utf-8' end p "aaaaaaaaaaaaaaaaaaaaaaaaaaa" p entry_name p "aaaaaaaaaaaaaaaaaaaaaaaaaaa" ext = File.extname(entry_name) #拡張子を取得 # 隠しファイルやゴミファイルは飛ばす next if ext.blank? || File.basename(entry_name).count(".") > 1 num += 1 if num > 30 then break end # 一時ファイルを作る Tempfile.open(["tempProductImageFile", ext]) do |t| entry.extract(t.path) { true } @product.send("products_image#{num}=", t) end end end この書き方は自分の環境ではできないようです。大変申し訳ないのですが、他のやり方はあるでしょうか。
s_diff

2018/12/21 10:56

また、それぞれのエンコードを試してみましたがascii-8bitのコードのままのようです。 entry.name.force_encoding('UTF-8') → "images/1/\x83n\x83C\x83g\x83\x8C\x83W\x83\x85\x83\x8A\x81[_ _\x8AO\x8A\xCF-2.jpg" entry.name.force_encoding('euc-jp') → "images/1/\x83n\x83C\x83g\x83\x8C\x83W\x83\x85\x83\x8A\x81[_ _\x8AO\x8A\xCF-2.jpg" entry.name.force_encoding('cp932') → "images/1/\x{836E}\x{8343}\x{8367}\x{838C}\x{8357}\x{8385}\x{838A}\x{815B}_ _\x{8A4F}\x{8ACF}-2.jpg" entry.name.force_encoding('utf-16') → "\x69\x6D\x61\x67\x65\x73\x2F\x31\x2F\x83\x6E\x83\x43\x83\x67\x83\x8C\x83\x57\x83\x85\x83\x8A\x81\x5B\x5F\x20\x5F\x8A\x4F\x8A\xCF\x2D\x32\x2E\x6A\x70\x67"
asm

2018/12/21 11:12

すいません guessに引数設定するの忘れてました
guest

0

Zip.unicode_names=trueを設定することで解決できるという記事がありました。
https://tmtms.hatenablog.com/entry/2017/04/10/rubyzip

検証してないので環境によってできないものがあるかもしれません。

投稿2018/12/21 09:48

dice142

総合スコア5158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

s_diff

2018/12/21 09:59

ご回答有難うございます。 Zip.unicode_names=trueはすでにコードにあるのですが、文字化けしています。
dice142

2018/12/21 10:04

すみません見落としてました。 別の原因探ってみます。
s_diff

2018/12/21 10:19

お手数ですが、よろしくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問