回答編集履歴

3

微修正

2017/10/17 02:47

投稿

abs123
abs123

スコア1280

test CHANGED
@@ -156,7 +156,7 @@
156
156
 
157
157
  offset = 0; // offsetのリセット
158
158
 
159
- Arrays.fill(data, 0); // 0埋めされてる必要はあるか?uploadの仕様次第
159
+ Arrays.fill(data, (byte)0); // 0埋めされてる必要はあるか?uploadの仕様次第
160
160
 
161
161
  // あと、uploadの処理が非同期の場合は新しくnewしたほうが安全かも
162
162
 

2

ソースコード追記

2017/10/17 02:47

投稿

abs123
abs123

スコア1280

test CHANGED
@@ -43,3 +43,179 @@
43
43
  実装の全体を見たわけではないので他の部分で送信データ量が制限されている可能性もありますが、
44
44
 
45
45
  ちょっと納得できない部分があるので参考程度に・・・
46
+
47
+
48
+
49
+ --- 10/17 追記 ---
50
+
51
+ スキル・知識というものはやってみないと身につかないものです。
52
+
53
+ 吐きながら覚えていきましょう。
54
+
55
+ 穴あきのソースを書いたのでこんな感じでやってみてください。
56
+
57
+ ```Java
58
+
59
+ public static void uploadPer512KBytes(InputStream in) throws IOException {
60
+
61
+ boolean next; // 繰り返しフラグ
62
+
63
+
64
+
65
+ // ストリームが終わるまでデータを読み込む外側ループ処理
66
+
67
+ do { // whileでも書けなくはないけど、1回は必ず内側を通る場合do-whileのほうが書きやすい
68
+
69
+
70
+
71
+ next = false; // 繰り返しフラグは外側ループの頭で毎回初期化する
72
+
73
+
74
+
75
+ // 512kbのデータを読み込む内側ループ処理
76
+
77
+ while ((bytesRead = in.read(data, offset, data.length - offset)) != -1) {
78
+
79
+
80
+
81
+ innerLoop++: // これはいくつになるかわからん
82
+
83
+
84
+
85
+ if (offset >= data.length) {
86
+
87
+ next = true; // ストリームの終わり以外で抜けるので繰り返しフラグをtrueに
88
+
89
+ break;
90
+
91
+ }
92
+
93
+
94
+
95
+ } // ストリームの終わりで抜けた場合は繰り返しフラグはfalseのまま
96
+
97
+
98
+
99
+ // 読み込んだデータの送信
100
+
101
+ if (offset >= 1) { // offset=0の状態でここに来ることがあるので
102
+
103
+       upload(bais);
104
+
105
+ }
106
+
107
+
108
+
109
+ outerLoop++; // これが4になるはず
110
+
111
+
112
+
113
+ } while(next); // 繰り返しフラグが立っている場合は外側処理をループ
114
+
115
+ }
116
+
117
+ ```
118
+
119
+ 下のコードは答え合わせ?用の動作未確認コードです。
120
+
121
+ 吐いたら見てください。
122
+
123
+ ```Java
124
+
125
+ // 答え合わせ?用
126
+
127
+
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+ public static void uploadPer512KBytes(InputStream in) throws IOException {
136
+
137
+ int offset;
138
+
139
+ int bytesRead;
140
+
141
+ byte[] data = new byte[524288];// バッファ
142
+
143
+ boolean next;
144
+
145
+ int outerLoop = 0;
146
+
147
+ int innerLoop = 0;
148
+
149
+
150
+
151
+ // ストリームが終わるまでデータを読み込む外側ループ処理
152
+
153
+ do { // whileでも書けなくはないけど、1回は必ず内側を通る場合do-whileのほうが書きやすい
154
+
155
+     // 外側ループ毎の初期化処理
156
+
157
+ offset = 0; // offsetのリセット
158
+
159
+ Arrays.fill(data, 0); // 0埋めされてる必要はあるか?uploadの仕様次第
160
+
161
+ // あと、uploadの処理が非同期の場合は新しくnewしたほうが安全かも
162
+
163
+ next = false; // 繰り返しフラグのリセット
164
+
165
+
166
+
167
+     // 512kbのデータを読み込む内側ループ処理
168
+
169
+ while ((bytesRead = in.read(data, offset, data.length - offset)) != -1) {
170
+
171
+ offset += bytesRead;
172
+
173
+ innerLoop++: // これはいくつになるかわからん
174
+
175
+ if (offset >= data.length) {
176
+
177
+ next = true; // ストリームの終わり以外で抜けるので繰り返しフラグをtrueに
178
+
179
+ break;
180
+
181
+ }
182
+
183
+ } // ストリームの終わりで抜けた場合は繰り返しフラグはfalseのまま
184
+
185
+
186
+
187
+ // 読み込んだデータの送信
188
+
189
+ if (offset >= 1) { // offset=0の状態でここに来ることがあるので
190
+
191
+ // 端っこのデータを処理する時、
192
+
193
+ // 引数1つのコンストラクタでは余計な部分まで処理することにならないか?
194
+
195
+ // uploadの仕様次第だが、引数3つのコンストラクタを使ったほうがいいような・・・
196
+
197
+ // ByteArrayInputStream bais = new ByteArrayInputStream(data, 0, offset);
198
+
199
+ ByteArrayInputStream bais = new ByteArrayInputStream(data);
200
+
201
+ // バッファに格納した分アップロード
202
+
203
+       upload(bais);
204
+
205
+ }
206
+
207
+
208
+
209
+ // offsetとdataの初期化処理は、ここでやることもできる。
210
+
211
+ // 最初の1回だけあらかじめデータを入れておきたい場合はここで
212
+
213
+
214
+
215
+ outerLoop++; // これが4になるはず
216
+
217
+ } while(next); // 繰り返しフラグが立っている場合は外側処理をループ
218
+
219
+ }
220
+
221
+ ```

1

修正

2017/10/17 01:34

投稿

abs123
abs123

スコア1280

test CHANGED
@@ -1,3 +1,45 @@
1
1
  InputStreamの実体がただのInputStreamである場合は、
2
2
 
3
3
  BufferedInputStreamでラップしてみてください。
4
+
5
+
6
+
7
+ --- 追記・・・というより書き直し ---
8
+
9
+ BufferedInputStream多分関係ありませんでした。
10
+
11
+ で、他に修正できそうなところがあったので書こうと思うのですが、
12
+
13
+ コメントで状態を確認してみたらよくわからなくなってきました。
14
+
15
+ とりあえず書いておきます。
16
+
17
+
18
+
19
+ 問題が発生していると思われるのは、While文の中です。
20
+
21
+ バッファが埋まる、またはストリームが終わるまでデータを繰り返し読み込む、
22
+
23
+ という処理を行っていると思うのですが、その中でuploadメソッドが呼ばれているため、
24
+
25
+ バッファが埋まり切っていない状態のデータを複数回送信してしまっているものと思います。
26
+
27
+ ※複数回の所が実行毎に違うのは、InputStreamにデータを入れる側の転送速度が実行毎に変わっているからだと思っています。
28
+
29
+
30
+
31
+ これを修正するには、While文を抜けた後でuploadメソッドを呼ぶように修正するだけなのですが、
32
+
33
+ それだとバッファ分の512Kbしか送れなくなるので、ストリームが終わったかを確認し、
34
+
35
+ ストリームが終わるまで処理を繰り返すWhile文を外側に作る必要があります。
36
+
37
+
38
+
39
+ といった感じなのですが、
40
+
41
+ この処理で行くと26回送った時点で13Mb近くのデータが送られていないとおかしいのです・・・
42
+
43
+ 実装の全体を見たわけではないので他の部分で送信データ量が制限されている可能性もありますが、
44
+
45
+ ちょっと納得できない部分があるので参考程度に・・・