質問するログイン新規登録

回答編集履歴

8

修正

2020/04/23 15:15

投稿

tanat
tanat

スコア18778

answer CHANGED
@@ -23,13 +23,12 @@
23
23
  > encoders to add line feeds after a specific number of characters.
24
24
 
25
25
  - その結果4のバイト倍数ずつ読み込むと改行コードも4バイトに含まれてしまい、Base64の1セットが崩れてしまう
26
- - bufferSizeがファイルより大きい場合は改行コードも合わせてデコード出来るので問題ない(base64_decode()が上手く判定している気がする)
26
+ - bufferSizeがファイルより大きい場合は改行コードも合わせてデコード出来るので問題ない(base64_decode()が上手く判定する)
27
27
 
28
28
 
29
29
  解決方法
30
30
  ---
31
- 1. 一回の読み込みを76の倍数にする
32
- 2. 一回の読み込みを(76バイト+改行コード)の倍数のバイト数にして、改行コードbase64_decode()に処理させる
31
+ 1. 一回の読み込みを(76バイト+改行コード)の倍数のバイト数にし改行コードも含めてbase64_decode()に処理させる
33
32
 
34
33
 
35
34
  ソース

7

追記

2020/04/23 15:15

投稿

tanat
tanat

スコア18778

answer CHANGED
@@ -2,7 +2,26 @@
2
2
 
3
3
  原因
4
4
  ---
5
- - zipをbase64エンコードすると76バイト毎に改行コードが挿入される(Base64の仕様(shouldなので必須では無い))
5
+ - base64エンコードすると76バイト毎に改行コードが挿入される(Base64の仕様(必須では無いがMIMEの仕様に合わせるためにデフォルトではそうなる実装が多いっぽい?))
6
+
7
+ [RFC The Base16, Base32, and Base64 Data Encodings](https://tools.ietf.org/html/rfc4648)
8
+
9
+
10
+ > 3.1. Line Feeds in Encoded Data
11
+ >
12
+ > MIME [4] is often used as a reference for base 64 encoding. However,
13
+ > MIME does not define "base 64" per se, but rather a "base 64 Content-
14
+ > Transfer-Encoding" for use within MIME. As such, MIME enforces a
15
+ > limit on line length of base 64-encoded data to 76 characters. MIME
16
+ > inherits the encoding from Privacy Enhanced Mail (PEM) [3], stating
17
+ > that it is "virtually identical"; however, PEM uses a line length of
18
+ > 64 characters. The MIME and PEM limits are both due to limits within
19
+ > SMTP.
20
+ >
21
+ > Implementations MUST NOT add line feeds to base-encoded data unless
22
+ > the specification referring to this document explicitly directs base
23
+ > encoders to add line feeds after a specific number of characters.
24
+
6
25
  - その結果4のバイト倍数ずつ読み込むと改行コードも4バイトに含まれてしまい、Base64の1セットが崩れてしまう
7
26
  - bufferSizeがファイルより大きい場合は改行コードも合わせてデコード出来るので問題ない(base64_decode()が上手く判定している気がする)
8
27
 

6

追記

2020/04/23 15:14

投稿

tanat
tanat

スコア18778

answer CHANGED
@@ -24,6 +24,7 @@
24
24
  $readed = 0;
25
25
  if($file = fopen($localFile , 'rb')){
26
26
  //MIMEに合わせて一回で読むバイト数を決め打ち。合計値をn倍してもOK。
27
+ //ここではエンコード環境がlinuxなので改行コードがLF(1バイト)になっているが、エンコード環境によってはCRLF(2バイト)になるはずなので、扱いたいファイルの仕様に合わせて変更する
27
28
  $bufferSize = 76+strlen(PHP_EOL);
28
29
  while(!feof($file)){
29
30
  $buffer = fread($file, $bufferSize);

5

MIMEに対する誤記を修正

2020/04/23 15:09

投稿

tanat
tanat

スコア18778

answer CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  原因
4
4
  ---
5
- - zipをbase64エンコードすると76バイト毎に改行コードが挿入される(MIMEの仕様)
5
+ - zipをbase64エンコードすると76バイト毎に改行コードが挿入される(Base64の仕様(shouldなので必須では無い)
6
- - その結果4バイトずつ読み込むと改行コードも4バイトに含まれてしまい、base64のセットが崩れてしまう
6
+ - その結果4バイト倍数ずつ読み込むと改行コードも4バイトに含まれてしまい、Base641セットが崩れてしまう
7
7
  - bufferSizeがファイルより大きい場合は改行コードも合わせてデコード出来るので問題ない(base64_decode()が上手く判定している気がする)
8
8
 
9
9
 

4

修正

2020/04/23 15:05

投稿

tanat
tanat

スコア18778

answer CHANGED
@@ -10,7 +10,7 @@
10
10
  解決方法
11
11
  ---
12
12
  1. 一回の読み込みを76の倍数にする
13
- 2. 一回の読み込み辺り、76バイトの倍数+改行コードを含めたバイト数を読み込んで、base64_decode()に処理させる
13
+ 2. 一回の読み込みを(76バイト+改行コード)の倍数のバイト数にして改行コードはbase64_decode()に処理させる
14
14
 
15
15
 
16
16
  ソース

3

環境追記

2020/04/23 15:01

投稿

tanat
tanat

スコア18778

answer CHANGED
@@ -1,4 +1,4 @@
1
- 興味があったので手元のdebianで試してみたところ、スマートでは無いですが解決できたので回答します。
1
+ 興味があったので手元のRaspbianで試してみたところ、スマートでは無いですが解決できたので回答します。
2
2
 
3
3
  原因
4
4
  ---
@@ -40,6 +40,16 @@
40
40
  検証
41
41
  ---
42
42
 
43
+ PHPのバージョン(検証していませんが、PHP5.5でも動くと思う)
44
+ ```bash
45
+ $ php -v
46
+ PHP 7.3.11-1~deb10u1 (cli) (built: Oct 26 2019 14:14:18) ( NTS )
47
+ Copyright (c) 1997-2018 The PHP Group
48
+ Zend Engine v3.3.11, Copyright (c) 1998-2018 Zend Technologies
49
+ with Zend OPcache v7.3.11-1~deb10u1, Copyright (c) 1999-2018, by Zend Technologies
50
+
51
+ ```
52
+
43
53
  テキストファイルの作成
44
54
  UTF-8で`test.txt`を作成
45
55
  ```text

2

修正

2020/04/23 14:59

投稿

tanat
tanat

スコア18778

answer CHANGED
@@ -47,11 +47,15 @@
47
47
  ```
48
48
 
49
49
  zip化
50
+ ```bash
50
- `$ zip test.zip test.txt
51
+ $ zip test.zip test.txt
51
52
  adding: test.txt (deflated 38%)`
53
+ ```
52
54
 
53
55
  base64dにエンコード
56
+ ```bash
54
- `$ base64 test.zip > test.bat`
57
+ $ base64 test.zip > test.bat`
58
+ ```
55
59
 
56
60
  エンコードされた内容の確認
57
61
  改行コードが入っていることがわかる

1

追記

2020/04/23 14:56

投稿

tanat
tanat

スコア18778

answer CHANGED
@@ -9,7 +9,8 @@
9
9
 
10
10
  解決方法
11
11
  ---
12
+ 1. 一回の読み込みを76の倍数にする
12
- 76バイト毎に改行が入ること見越して改行分を読み捨て(base64自体は改行コードは必要としない)
13
+ 2. 一回の読み込み辺り、76バイトの倍数+改行コード含めたバイト数を読み込んで、base64_decode()に処理させ
13
14
 
14
15
 
15
16
  ソース
@@ -22,8 +23,8 @@
22
23
 
23
24
  $readed = 0;
24
25
  if($file = fopen($localFile , 'rb')){
25
- //MIMEに合わせて一回で読むバイト数を決め打ち。76の数ならなんでいけるはず
26
+ //MIMEに合わせて一回で読むバイト数を決め打ち。合計値をnしてOK
26
- $bufferSize = 76;
27
+ $bufferSize = 76+strlen(PHP_EOL);
27
28
  while(!feof($file)){
28
29
  $buffer = fread($file, $bufferSize);
29
30
  echo base64_decode($buffer);