質問編集履歴

5

タブの追加

2021/05/28 17:51

投稿

nekora
nekora

スコア501

test CHANGED
File without changes
test CHANGED
File without changes

4

書式の改善

2021/05/28 17:51

投稿

nekora
nekora

スコア501

test CHANGED
File without changes
test CHANGED
@@ -1,3 +1,5 @@
1
+ ### やった事
2
+
1
3
  参考リンクのコード例をベースにして、
2
4
 
3
5
 
@@ -10,6 +12,8 @@
10
12
 
11
13
 
12
14
 
15
+ ### お聞きしたい事
16
+
13
17
  しかし、
14
18
 
15
19
  **参考URLのサンプルコードでPHP内のクライアントサイドのコードがHTMLではなくXHTMLになっている理由が分かりません。**
@@ -32,7 +36,7 @@
32
36
 
33
37
 
34
38
 
35
- 参考にしたURL
39
+ ### 参考にしたURL
36
40
 
37
41
  [PHP+MySQLで簡易画像アップローダ](https://qiita.com/mpyw/items/117ab6a88fd58d911c34)
38
42
 

3

ソースコードの公開

2021/05/28 17:43

投稿

nekora
nekora

スコア501

test CHANGED
File without changes
test CHANGED
@@ -35,3 +35,407 @@
35
35
  参考にしたURL
36
36
 
37
37
  [PHP+MySQLで簡易画像アップローダ](https://qiita.com/mpyw/items/117ab6a88fd58d911c34)
38
+
39
+
40
+
41
+ 参考サイトのコード、実際にはDELETE機能やページャーなどを組み込み済み
42
+
43
+ ```PHP
44
+
45
+ <?php
46
+
47
+
48
+
49
+ /* HTML特殊文字をエスケープする関数 */
50
+
51
+ function h($str) {
52
+
53
+ return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
54
+
55
+ }
56
+
57
+
58
+
59
+ // XHTMLとしてブラウザに認識させる
60
+
61
+ // (IE8以下はサポート対象外w)
62
+
63
+ header('Content-Type: application/xhtml+xml; charset=utf-8');
64
+
65
+
66
+
67
+ try {
68
+
69
+
70
+
71
+ // データベースに接続
72
+
73
+ $pdo = new PDO(
74
+
75
+ 'mysql:host=localhost;dbname=imagedb;charset=utf8',
76
+
77
+ 'root',
78
+
79
+ '',
80
+
81
+ [
82
+
83
+ PDO::ATTR_EMULATE_PREPARES => false,
84
+
85
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
86
+
87
+ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
88
+
89
+ ]
90
+
91
+ );
92
+
93
+
94
+
95
+ /* アップロードがあったとき */
96
+
97
+ if (isset($_FILES['upfile']['error']) && is_int($_FILES['upfile']['error'])) {
98
+
99
+
100
+
101
+ // バッファリングを開始
102
+
103
+ ob_start();
104
+
105
+
106
+
107
+ try {
108
+
109
+
110
+
111
+ // $_FILES['upfile']['error'] の値を確認
112
+
113
+ switch ($_FILES['upfile']['error']) {
114
+
115
+ case UPLOAD_ERR_OK: // OK
116
+
117
+ break;
118
+
119
+ case UPLOAD_ERR_NO_FILE: // ファイル未選択
120
+
121
+ throw new RuntimeException('ファイルが選択されていません', 400);
122
+
123
+ case UPLOAD_ERR_INI_SIZE: // php.ini定義の最大サイズ超過
124
+
125
+ case UPLOAD_ERR_FORM_SIZE: // フォーム定義の最大サイズ超過
126
+
127
+ throw new RuntimeException('ファイルサイズが大きすぎます', 400);
128
+
129
+ default:
130
+
131
+ throw new RuntimeException('その他のエラーが発生しました', 500);
132
+
133
+ }
134
+
135
+
136
+
137
+ // $_FILES['upfile']['mime']の値はブラウザ側で偽装可能なので
138
+
139
+ // MIMEタイプを自前でチェックする
140
+
141
+ if (!$info = @getimagesize($_FILES['upfile']['tmp_name'])) {
142
+
143
+ throw new RuntimeException('有効な画像ファイルを指定してください', 400);
144
+
145
+ }
146
+
147
+ if (!in_array($info[2], [IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG], true)) {
148
+
149
+ throw new RuntimeException('未対応の画像形式です', 400);
150
+
151
+ }
152
+
153
+
154
+
155
+ // サムネイルをバッファに出力
156
+
157
+ $create = str_replace('/', 'createfrom', $info['mime']);
158
+
159
+ $output = str_replace('/', '', $info['mime']);
160
+
161
+ if ($info[0] >= $info[1]) {
162
+
163
+ $dst_w = 120;
164
+
165
+ $dst_h = ceil(120 * $info[1] / max($info[0], 1));
166
+
167
+ } else {
168
+
169
+ $dst_w = ceil(120 * $info[0] / max($info[1], 1));
170
+
171
+ $dst_h = 120;
172
+
173
+ }
174
+
175
+ if (!$src = @$create($_FILES['upfile']['tmp_name'])) {
176
+
177
+ throw new RuntimeException('画像リソースの生成に失敗しました', 500);
178
+
179
+ }
180
+
181
+ $dst = imagecreatetruecolor($dst_w, $dst_h);
182
+
183
+ imagecopyresampled($dst, $src, 0, 0, 0, 0, $dst_w, $dst_h, $info[0], $info[1]);
184
+
185
+ $output($dst);
186
+
187
+ imagedestroy($src);
188
+
189
+ imagedestroy($dst);
190
+
191
+
192
+
193
+ // INSERT処理
194
+
195
+ $stmt = $pdo->prepare('INSERT INTO image(name,type,raw_data,thumb_data,date) VALUES(?,?,?,?,?)');
196
+
197
+ $stmt->execute([
198
+
199
+ $_FILES['upfile']['name'],
200
+
201
+ $info[2],
202
+
203
+ file_get_contents($_FILES['upfile']['tmp_name']),
204
+
205
+ ob_get_clean(), // バッファからデータを取得してクリア
206
+
207
+ (new DateTime('now', new DateTimeZone('Asia/Tokyo')))->format('Y-m-d H:i:s'),
208
+
209
+ ]);
210
+
211
+
212
+
213
+ $msgs[] = ['green', 'ファイルは正常にアップロードされました'];
214
+
215
+
216
+
217
+ } catch (RuntimeException $e) {
218
+
219
+
220
+
221
+ while (ob_get_level()) {
222
+
223
+ ob_end_clean(); // バッファをクリア
224
+
225
+ }
226
+
227
+ http_response_code($e instanceof PDOException ? 500 : $e->getCode());
228
+
229
+ $msgs[] = ['red', $e->getMessage()];
230
+
231
+
232
+
233
+ }
234
+
235
+
236
+
237
+ /* ID指定があったとき */
238
+
239
+ } elseif (isset($_GET['id'])) {
240
+
241
+
242
+
243
+ try {
244
+
245
+
246
+
247
+ $stmt = $pdo->prepare('SELECT type, raw_data FROM image WHERE id = ? LIMIT 1');
248
+
249
+ $stmt->bindValue(1, $_GET['id'], PDO::PARAM_INT);
250
+
251
+ $stmt->execute();
252
+
253
+ if (!$row = $stmt->fetch()) {
254
+
255
+ throw new RuntimeException('該当する画像は存在しません', 404);
256
+
257
+ }
258
+
259
+ header('X-Content-Type-Options: nosniff');
260
+
261
+ header('Content-Type: ' . image_type_to_mime_type($row['type']));
262
+
263
+ echo $row['raw_data'];
264
+
265
+ exit;
266
+
267
+
268
+
269
+ } catch (RuntimeException $e) {
270
+
271
+
272
+
273
+ http_response_code($e instanceof PDOException ? 500 : $e->getCode());
274
+
275
+ $msgs[] = ['red', $e->getMessage()];
276
+
277
+
278
+
279
+ }
280
+
281
+
282
+
283
+ }
284
+
285
+
286
+
287
+ // サムネイル一覧取得
288
+
289
+ $rows = $pdo->query('SELECT id,name,type,thumb_data,date FROM image ORDER BY date DESC')->fetchAll();
290
+
291
+
292
+
293
+ } catch (PDOException $e) {
294
+
295
+
296
+
297
+ http_response_code(500);
298
+
299
+ $msgs[] = ['red', $e->getMessage()];
300
+
301
+
302
+
303
+ }
304
+
305
+
306
+
307
+ ?>
308
+
309
+ <!DOCTYPE html>
310
+
311
+ <html xmlns="http://www.w3.org/1999/xhtml">
312
+
313
+ <head>
314
+
315
+ <title>画像アップロード</title>
316
+
317
+ <style><![CDATA[
318
+
319
+ fieldset { margin: 10px; }
320
+
321
+ legend { font-size: 12pt; }
322
+
323
+ img {
324
+
325
+ border: none;
326
+
327
+ float: left;
328
+
329
+ }
330
+
331
+ ]]></style>
332
+
333
+ </head>
334
+
335
+ <body>
336
+
337
+ <form enctype="multipart/form-data" method="post" action="">
338
+
339
+ <fieldset>
340
+
341
+ <legend>画像ファイルを選択(GIF, JPEG, PNGのみ対応)</legend>
342
+
343
+ <input type="file" name="upfile" /><br />
344
+
345
+ <input type="submit" value="送信" />
346
+
347
+ </fieldset>
348
+
349
+ </form>
350
+
351
+ <?php if (!empty($msgs)): ?>
352
+
353
+ <fieldset>
354
+
355
+ <legend>メッセージ</legend>
356
+
357
+ <?php foreach ($msgs as $msg): ?>
358
+
359
+ <ul>
360
+
361
+ <li style="color:<?=h($msg[0])?>;"><?=h($msg[1])?></li>
362
+
363
+ </ul>
364
+
365
+ <?php endforeach; ?>
366
+
367
+ </fieldset>
368
+
369
+ <?php endif; ?>
370
+
371
+ <?php if (!empty($rows)): ?>
372
+
373
+ <fieldset>
374
+
375
+ <legend>サムネイル一覧(クリックすると原寸大表示)</legend>
376
+
377
+ <?php foreach ($rows as $i => $row): ?>
378
+
379
+ <?php if ($i): ?>
380
+
381
+ <hr />
382
+
383
+ <?php endif; ?>
384
+
385
+ <p>
386
+
387
+ <?=sprintf(
388
+
389
+ '<a href="?id=%d"><img src="data:%s;base64,%s" alt="%s" /></a>',
390
+
391
+ $row['id'],
392
+
393
+ image_type_to_mime_type($row['type']),
394
+
395
+ base64_encode($row['thumb_data']),
396
+
397
+ h($row['name'])
398
+
399
+ )?><br />
400
+
401
+ ファイル名: <?=h($row['name'])?><br />
402
+
403
+ 日付: <?=h($row['date'])?><br clear="all" />
404
+
405
+ </p>
406
+
407
+ <?php endforeach; ?>
408
+
409
+ </fieldset>
410
+
411
+ <?php endif; ?>
412
+
413
+ </body>
414
+
415
+ </html>
416
+
417
+ ```
418
+
419
+
420
+
421
+ 参考サイトのSQL
422
+
423
+ ```SQL
424
+
425
+ CREATE TABLE image(
426
+
427
+ `id` int UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT 'ID',
428
+
429
+ `name` varchar(255) NOT NULL COMMENT 'ファイル名',
430
+
431
+ `type` tinyint(2) NOT NULL COMMENT 'IMAGETYPE定数',
432
+
433
+ `raw_data` mediumblob NOT NULL COMMENT '原寸大データ',
434
+
435
+ `thumb_data` blob NOT NULL COMMENT 'サムネイルデータ',
436
+
437
+ `date` datetime NOT NULL COMMENT '日付'
438
+
439
+ ) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci
440
+
441
+ ```

2

やったことの追記

2021/05/28 17:38

投稿

nekora
nekora

スコア501

test CHANGED
File without changes
test CHANGED
@@ -1,6 +1,12 @@
1
- 参考リンクのコード例をベースにして、ドラッグアンドドロップ、INPUTタグでの複数ファイル同時選択、
1
+ 参考リンクのコード例をベースにして、
2
2
 
3
+
4
+
5
+ ドラッグアンドドロップ、INPUTタグでの複数ファイル同時選択、DELETE機能の実装、ページャーの実装、LOADING画面での操作ロック、
6
+
7
+ DBにファイル本体の登録ではなくURLの登録にして、実ファイルをwordpressのアップローダー準拠で年度、月のフォルダに分けて格納、
8
+
3
- DELETE機能の装、ページャー実装、LOADING画面の操作ロックの実装も終えアップローダー自体は完成しました。
9
+ BASIC認証、ファイルフォルダみ認証なし外部から参照できるように実装も終えアップローダー自体は完成しました。
4
10
 
5
11
 
6
12
 

1

誤字の修正

2021/05/28 17:10

投稿

nekora
nekora

スコア501

test CHANGED
File without changes
test CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
 
18
18
 
19
- 実は、当方チームリーダーの立場にあって、新人に完成したコードの設枚をしなければならないのですが、
19
+ 実は、当方チームリーダーの立場にあって、新人に完成したコードの説明をしなければならないのですが、
20
20
 
21
21
  **サンプルソースがこうなっていたからでは理由にならず、立つ瀬がありません。**
22
22