developer's diary

最近はc#のエントリが多いです

PHPでPDF出力 ~ dompdfを利用した「ええ感じ」のサンプル(htmlを利用)

tcpdfはこちら

tcpdfバージョンのエントリは以下より。

mitsugeek.net

dompdfの準備

プロジェクト用ディレクトリ作成

mkdir pdf-example2

ディレクトリに移動

mkdir pdf-example2

composerの準備

composer init

dompdfのインストール

composer require dompdf/dompdf

load_font.phpの準備

curl https://raw.githubusercontent.com/dompdf/utils/master/load_font.php --output load_font.php

IPAフォントのダウンロードと解凍

curl https://ipafont.ipa.go.jp/IPAfont/IPAfont00303.zip --output IPAfont00303.zip
unzip IPAfont00303.zip 

フォントの追加

php load_font.php ipag IPAfont00303/ipag.ttf
php load_font.php ipagp IPAfont00303/ipagp.ttf  
php load_font.php ipam IPAfont00303/ipam.ttf 
php load_font.php ipamp IPAfont00303/ipamp.ttf

画像埋め込みの確認用に猫の画像を検索してダウンロードしておく

ここで猫の画像を検索 visualhunt.com

f:id:mitsugi-bb:20200907230618p:plain
この猫の画像にしよう

名前はcat.phpにしよう。

phpファイル作成

imgタグはどうもネットワーク経由で取得しているらしく、URLが必要だった。 ローカルのファイルを利用する場合は、base64を利用することでうまくいく。 今回はローカルファイルで対応した為、base64で事前に読み込んでおく。

<?php
require_once "vendor/autoload.php";

use Dompdf\Dompdf;

$img = base64_encode(file_get_contents("cat.jpg"));
$html = <<< EOF
<style>
body {
    font-family: ipag;
    }
.td {
    border: solid 1px black;
}
.td2 {
    border: solid 1px black;
    height:100px;
}
.td3 {
    font-size:20px;
    border: solid 1px black;
    height:100px;
}
.table{
    width:100%;
    border-collapse: collapse;
    border-spacing: 0px;
}
.left{
    text-align: left;
    border: solid 1px black;
    height:30px;
}
.right{
    text-align: right;
    border: solid 1px black;
    height:30px;
}
.center{
    text-align: center;
    border: solid 1px black;
    height:30px;
}
.decoration{
    text-decoration: line-through;
    border: solid 1px black;
}

.sample1 {text-decoration: none;}
.sample2 {text-decoration: underline;}
.sample3 {text-decoration: overline;}
.sample4 {text-decoration: line-through;}
.sample5 {text-decoration: underline dotted red;}

.color{
    background-color:black;
    color:white;
}
</style>


<table class="table">
<tr>
    <td class="left">text-align: left;</td>
    <td class="center">text-align: center;</td>
    <td class="right">text-align: right;</td>
</tr>
<tr>
    <td class="td">test</td>
    <td class="td">日本語</td>
    <td class="td">hoge</td>
</tr>
<tr>
    <td class="td">test</td>
    <td class="td"><table class="table">
        <tr>
            <td class="td" >test</td>
        </tr>
        <tr>
            <td class="td" >test</td>
        </tr>
    </table></td>
    <td class="td">hoge</td>
</tr>
<tr>
    <td class="td" colspan="2">colspan="2"</td>
    <td class="td" rowspan="2">rowspan="2"</td>
</tr>
<tr>
    <td class="td">test</td>
    <td class="td">fuga</td>
</tr>
<tr>
    <td class="td2" colspan="3">height:100px; colspan="3"</td>
</tr>
<tr>
    <td class="td2 color" colspan="3">改行<br>
brタグ<br>
で改行<br>
背景色変更<br>
フォントカラー変更<br>
</td>
</tr>
<tr>
    <td class="td3" colspan="3">改行<br>
brタグ<br>
で改行<br>
</td>
</tr>
<tr>
<td class="td2" colspan="3">

<div><span class="sample1">none</span> text-decoration: none;</div>
<div><span class="sample2">underline</span> text-decoration: underline;</div>
<div><span class="sample3">overline</span> text-decoration: overline;</div>
<div><span class="sample4">line-through</span> text-decoration: line-through;</div>
<div><span class="sample5">underline dotted red</span> text-decoration: underline dotted red;</div>


</td>
</tr>
<tr>
<td class="td2" colspan="3">
画像挿入
<br>
<div>
 <img src="data:image/jpeg;base64,{$img}" width="300px"/> 
</div>
<br>

</td>
</tr>
</table>


EOF;

$dompdf = new Dompdf();

$dompdf->loadHtml($html);

$options = $dompdf->getOptions(); 
$options->set(array('isRemoteEnabled' => false));
$dompdf->setOptions($options);

$dompdf->setPaper('A4', 'portrait');
$dompdf->render();

$dompdf->stream("example.pdf", array("Attachment" => true));

結果

f:id:mitsugi-bb:20200908004730p:plain
urlを開くとファイルダウンロードが行われる
f:id:mitsugi-bb:20200908004751p:plain
PDFの読み込み結果

PHPでPDF出力 ~ tcpdfを利用した「ええ感じ」のサンプル(htmlを利用)

dompdfはこちら

dompdfバージョンのエントリは以下より。

mitsugeek.net

tcpdfの準備

プロジェクト用ディレクトリ作成

mkdir pdf-example

ディレクトリに移動

mkdir pdf-example

composer初期化

composer init

tcpdfインストール

composer require tecnickcom/tcpdf

IPAフォントダウンロード、解凍

curl https://ipafont.ipa.go.jp/IPAfont/IPAfont00303.zip --output IPAfont00303.zip
unzip IPAfont00303.zip 

tcpdfに日本語用フォント追加

php vendor/tecnickcom/tcpdf/tools/tcpdf_addfont.php -b -t ipag -f 32 -i ./IPAfont00303/ipag.ttf 
php vendor/tecnickcom/tcpdf/tools/tcpdf_addfont.php -b -t ipagp -f 32 -i ./IPAfont00303/ipagp.ttf 
php vendor/tecnickcom/tcpdf/tools/tcpdf_addfont.php -b -t ipam -f 32 -i ./IPAfont00303/ipam.ttf 
php vendor/tecnickcom/tcpdf/tools/tcpdf_addfont.php -b -t ipamp -f 32 -i ./IPAfont00303/ipamp.ttf

画像埋め込みの確認用に猫の画像を検索してダウンロードしておく

ここで猫の画像を検索 visualhunt.com

f:id:mitsugi-bb:20200907230618p:plain
この猫の画像にしよう

名前はcat.phpにしよう。

phpファイル作成

それなりに、HTMLは色々と盛り込んでみました。

<?php

// composerでインストールしたライブラリを参照する
require_once('./vendor/tecnickcom/tcpdf/tcpdf.php');

// 用紙の方向、用紙サイズを指定する
$tcpdf = new TCPDF('P', "pt",'A4');
$tcpdf->SetMargins(5, 5, 5); //マージン無効
$tcpdf->SetFont('ipag', '', 10);
$tcpdf->setPrintHeader(false);
$tcpdf->setPrintFooter(false);
$tcpdf->AddPage();

$html = <<< EOF
<style>
.td {
    border: solid 1px black;
}
.td2 {
    border: solid 1px black;
    height:100px;
}
.td3 {
    font-size:20px;
    border: solid 1px black;
    height:100px;
}
.table{
    border-collapse: collapse;
    border-spacing: 0px;
}
.left{
    text-align: left;
    border: solid 1px black;
    height:30px;
}
.right{
    text-align: right;
    border: solid 1px black;
    height:30px;
}
.center{
    text-align: center;
    border: solid 1px black;
    height:30px;
}
.decoration{
    text-decoration: line-through;
    border: solid 1px black;
}

.sample1 {text-decoration: none;}
.sample2 {text-decoration: underline;}
.sample3 {text-decoration: overline;}
.sample4 {text-decoration: line-through;}
.sample5 {text-decoration: underline dotted red;}

.color{
    background-color:black;
    color:white;
}
</style>


<table class="table">
<tr>
    <td class="left">text-align: left;</td>
    <td class="center">text-align: center;</td>
    <td class="right">text-align: right;</td>
</tr>
<tr>
    <td class="td">test</td>
    <td class="td">日本語</td>
    <td class="td">hoge</td>
</tr>
<tr>
    <td class="td">test</td>
    <td class="td"><table class="table">
        <tr>
            <td class="td" >test</td>
        </tr>
        <tr>
            <td class="td" >test</td>
        </tr>
    </table></td>
    <td class="td">hoge</td>
</tr>
<tr>
    <td class="td" colspan="2">colspan="2"</td>
    <td class="td" rowspan="2">rowspan="2"</td>
</tr>
<tr>
    <td class="td">test</td>
    <td class="td">fuga</td>
</tr>
<tr>
    <td class="td2" colspan="3">height:100px; colspan="3"</td>
</tr>
<tr>
    <td class="td2 color" colspan="3">改行<br>
brタグ<br>
で改行<br>
背景色変更<br>
フォントカラー変更<br>
</td>
</tr>
<tr>
    <td class="td3" colspan="3">改行<br>
brタグ<br>
で改行<br>
</td>
</tr>
<tr>
<td class="td2" colspan="3">

<div><span class="sample1">none</span> text-decoration: none;</div>
<div><span class="sample2">underline</span> text-decoration: underline;</div>
<div><span class="sample3">overline</span> text-decoration: overline;</div>
<div><span class="sample4">line-through</span> text-decoration: line-through;</div>
<div><span class="sample5">underline dotted red</span> text-decoration: underline dotted red;</div>


</td>
</tr>
<tr>
<td class="td2" colspan="3">
画像挿入
<br>
<div>
 <img src="cat.jpg" width="300px"/> 
</div>
<br>

</td>
</tr>
</table>


EOF;

$tcpdf->WriteHTML($html, true, 0, false, true, 'L');
// 出力用バッファの内容を消去
ob_end_clean();
$tcpdf->Output("test.pdf", "D");

結果

URLを開くとファイルがダウンロードされます。

f:id:mitsugi-bb:20200907231027p:plain
ダウンロードの様子

ファイルを開くとこんな感じに。

f:id:mitsugi-bb:20200907231211p:plain
PDFの読み込み結果

参考

qiita.com

WSL + Ubuntu + PHP + xdebug + Visual StudioCode + PHP DebugでPHPの学習環境構築

前提
  • OSがWindows 10 Proであること。
  • WSLを有効化していること。
  • WSLにUbuntuインストール済みであること。
  • WSLのUbuntuにPHPインストール済みであること。
  • ローカル環境にVisual Studio Codeインストール済みであること。

Ubuntuにphp-xdebugをインストール

sudo apt install php-xdebug

php-xdebugの設定ファイルを修正

vi で設定ファイルを開く

sudo vi /etc/php/7.2/cli/conf.d/20-xdebug.ini

設定ファイルの内容を以下のように修正

zend_extension=xdebug.so
xdebug.remote_enable=on
xdebug.remote_autostart = 1

Visual Studio CodeにPHP Debugをインストール

赤色の枠の部分をクリックしていく。

PHP Debugをインストールする様子
PHP Debugをインストール

Visual Studio CodeにインストールしたPHP Debugの設定

設定ファイル(.vscode/launch.json)は、歯車マークをクリックして開けられる

PHP Debugの設定ファイルの開き方
PHP Debugの設定ファイルの開き方

設定ファイル(.vscode/launch.json)を以下のように修正

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "php local debug",
            "type": "php",
            "request": "launch",
            "port": 9000,
            "pathMappings": {
                "/mnt/c":"c:/"
            }
        }
    ]
}

準備OK!デバッグ実行してみよう。

  • 赤〇で囲った虫を押下。
  • オレンジで囲ったところをクリックしてブレークポイントを指定
  • 緑で囲ったところを「php local debug(ここはlaunch.jsonに指定したnameが表示される)」に変更して再生ボタンを押下
  • 水色で囲った部分にターミナルを表示しておく(ここでプログラムの実行を行う)

PHP Debugの準備
PHP Debugの準備

プログラムは以下の通り

<?php

echo "hello\n";
echo "hello\n";

$test = "test";

$number = 100;

$number2 = 200;

$number3 = $number + $number2;

プログラム実行してみる。

wsl php echo.php

PHP Debugのブレークポイントで止まった様子
PHP Debugのブレークポイントで止まった様子

ブレークポイントで止まった。

ステップオーバーしてみる。

赤〇で囲ったのアイコンをクリックして、1行ステップオーバー(プログラムが1行進む)

ステップオーバーの様子
ステップオーバーの様子

オレンジ色で囲ったところで変数の中身も確認できる。

感想

apacheをインストールする必要もなく、 簡単にできた。

こんな感じでPHPがステップ実行できると、 プログラム初級の部分(変数・演算・分岐・ループ・関数)で躓きにくくなるかもしれない。

改めて、Visual Studio Code の凄さを実感。

これが無償で利用できるなんて。。。

参考

togetter.com

togetter.com

togetter.com

参考にしたサイト

Setting up PHP for development on Windows Subsystem for Linux in Windows 10 | Tim Anderson's IT Writing

POP3を利用してメール受信する際に重複を防ぐ仕組み。「UIDL」を利用する

メールの受信処理でメール受信をトリガーにコマンド実行できない場合は、cronでx分単位で定時バッチを実行するのが一般的だと思います。

その際に受信したデータをメールサーバに残したままだと、何度も処理済みのデータを受信する羽目になってしまいます。

今回はそれをどうやって防ぐかという内容。

結論

「uidl」を利用します。

参考:重複せずに POP サーバからメールを受信する仕組み UIDL

PHPでUIDLを確認

ライブラリは「Net/POP3.php」を利用してます。

<?php
require_once 'Net/POP3.php';

$pop = new Net_POP3();
$pop->connect(HOST, PORT);
$pop->login(USER, PASS);
$messages = $pop->getListing();

foreach($messages as $message){
    var_dump($message);
}

結果

array(3) {
  ["msg_id"]=>
  string(1) "1"
  ["size"]=>
  string(5) "74529"
  ["uidl"]=>
  string(35) "494902.IMUdeXl3re8levBIsfglvt47mt4w="
}

array(3) {
  ["msg_id"]=>
  string(1) "2"
  ["size"]=>
  string(5) "34529"
  ["uidl"]=>
  string(35) "494932.IMUdeXl3re8erev4Is2vter7mt4w="
}

getListingで取得した結果を単純に回してvar_dumpしているだけですが、["uidl"]が確認できました。

あとはこれを処理後にDBに保存して、次回DBを参照した際に存在すればスキップすればいいだけですね。超簡単だ。

Microsoft Translatorに登録。クラウドを利用して翻訳プログラムを簡単に作る。

Microsoft Translatorって何?

Microsoftが提供する機械翻訳のAPIです。 Windows azure(マイクロソフトが提供するクラウドサービス)のMarketplace(データの方)にあります。

ということで登録しました。

月額2,000,000文字まで無料で利用できるようなので登録しました。

f:id:mitsugi-bb:20140105192859p:plain

試してみる。

↓のような感じにAPIを試す画面が存在します。

f:id:mitsugi-bb:20140105193301p:plain

初めまして。私はmitsugeekです。

↓↓↓Translator実行!↓↓↓

How do you do. I am mitsugeek.

単にこれだけだと、Google翻訳や、Yahoo翻訳等のWeb上の翻訳と変わりないです。

Webで利用できる翻訳サービス一覧

WEBの翻訳サービスって結構あるんですね。

何が嬉しい?

何が良いかというと自分のアプリケーションに翻訳機能を組み込める所です。 Googleも同様のサービス(Google Translate API)を行ってますが有料です。

プログラムから呼び出してみる。

手っ取り早くPHPで実行しました。

<?php

const APPID = 'プライマリ アカウント キーを入力';
$input_text = '初めまして。mitsugeekです。';
$to = 'en';

$ch = curl_init('https://api.datamarket.azure.com/Bing/MicrosoftTranslator/v1/Translate?Text=%27'.urlencode($input_text).'%27&To=%27'.$to.'%27');
curl_setopt($ch, CURLOPT_USERPWD, APPID.':'.APPID);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$result = curl_exec($ch);
$result = explode('<d:Text m:type="Edm.String">', $result);
$result = explode('</d:Text>', $result[1]);
$result = $result[0];

echo $input_text." -> ".$result;

結果。

f:id:mitsugi-bb:20140105201714p:plain

コマンドで実行。

[root@localhost html]# php mst.php
初めまして。mitsugeekです。 -> How do you do. It is mitsugeek.

simple_html_domでtitleとdescriptionを取得する。

PHPで簡単にパーサーするなら、simple_html_domが楽ちん。 大量にパーサーすると、遅いです。 過去に楽天の価格情報を取得するプログラムとか作ったことがあるのですが、 nodejsに変更した覚えがあります。

ソース

<?php
require_once 'simple_html_dom.php';
$html = new simple_html_dom();
$data = file_get_contents("http://www.yahoo.co.jp/");
$html->load($data);
$title = array_shift($html->find('title'))->innertext;
$description = array_shift($html->find("meta[name='description']"))->content;

echo $title."\n";
echo $description."\n";

実行結果

Yahoo! JAPAN
日本最大級のポータルサイト。検索、オークション、ニュース、天気、スポーツ、メール、ショッピングなど多数のサービスを展開。あなたの生活をより豊かにする「課題解決エンジン」を目指していきます。

Yahoo! JAPANって「課題解決エンジン」なんですね。

PHPでFTPで上書き更新のMVP(実用最小限の製品)

昨日リーンスタートアップの勉強会に参加しましたので、リーンスタートアップの用語を使いたくて使いたくてタマラナイmitsugeekです。

朝はやく(1時)に起きて眠れないので、ふとFTPのアップロードを自動化できれば楽しいんじゃないかと先ほど思いまして早速試してみました。

やってみて感じた事ですが、awsでのs3へのアクセスよりずっと簡単だということ。(rpmでインストールしたphpでそのまま使える) で参考までにソースを。

<?php
$ftp = ftp_connect('{サーバのIP}', {サーバのport}); //サーバに接続 (コネクションを開く)
$login_result = ftp_login($ftp, 'ユーザID', 'パスワード'); //サーバにログイン
$contents = "アップロードしたいファイルの内容"; //ファイルの内容を記述
$tempHandle = fopen('php://temp', 'r+'); //一時的なファイルを作成
fwrite($tempHandle, $contents); //ファイルに書き込み
rewind($tempHandle); //ファイルポインタの位置を先頭に戻す
ftp_fput($ftp, "/サーバのパス", $tempHandle, {FTP_ASCII or FTP_BINARY}); //ファイルアップロード
ftp_close($ftp); //サーバのコネクションを閉じる

これだけなんですが、

  1. テンプレートファイル読み込み
  2. データベースから情報取得
  3. テンプレートに情報を流し込む
  4. FTPでアップロード

の仕組みだけでも結構役立つと思います(個人的に)

欲をかけば、gitサーバ立ててpushしたらftpでテストサーバにアップして、 OKだったら管理画面からボタン押下で本番にデプロイまでの仕組みも作り込みたい。。。

そんなに難しくない割に、結構役立つ費用対効果の高いものが大好きなmitsugeekでした。

AWS SDK for PHP 2のインストール 〜 S3のバケット一覧取得まで

やりたいこと。

S3へPHPからアクセスしたい。

AWS SDK for PHP 2のインストール

composerをインストールします。 composerはruby bundlerのようなものだそうです。

curl -s http://getcomposer.org/installer | php

上記コマンドを実行すると、composer.pharがカレントディレクトリに作成されます。

次にcomposer.jsonを作成いします。(パッケージの記述)

vi composer.json

composer.jsonの内容

{
  "require": {
      "aws/aws-sdk-php": "*"
  }
}

install実行(composer.jsonに記載されたパッケージのインストール)

php composer.phar install

実行すると標準出力に以下のメッセージが。

Loading composer repositories with package information
Installing dependencies (including require-dev)
  - Installing symfony/event-dispatcher (v2.3.0)
    Downloading: 100%         

  - Installing guzzle/guzzle (v3.6.0)
    Downloading: 100%         

  - Installing aws/aws-sdk-php (2.3.4)
    Downloading: 100%         

symfony/event-dispatcher suggests installing symfony/dependency-injection ()
symfony/event-dispatcher suggests installing symfony/http-kernel ()
aws/aws-sdk-php suggests installing doctrine/cache (Adds support for caching of credentials and responses)
aws/aws-sdk-php suggests installing ext-apc (Allows service description opcode caching, request and response caching, and credentials caching)
aws/aws-sdk-php suggests installing monolog/monolog (Adds support for logging HTTP requests and responses)
aws/aws-sdk-php suggests installing symfony/yaml (Eases the ability to write manifests for creating jobs in AWS Import/Export)
Writing lock file
Generating autoload files

lsするとこんな感じです。

[mitsugeek@example ~]$ ls
composer.json  composer.lock  composer.phar  vendor

vendorディレクトリとcomposer.lock が作成されました。

以上で【AWS SDK for PHP 2】のインストール完了です。

ひきつづきS3へのアクセスを行いたいと思います。

S3のバケット取得プログラム

vi s3_listBuckets_example.php
<?php

require_once("/var/www/html/dev/vendor/autoload.php");

use Aws\S3\S3Client;

$config = array(
  'key'    => 'keyを記載',
  'secret' => 'secretを記載'
);

$s3 = S3Client::factory($config);

$buckets= $s3->listBuckets();
foreach ($buckets as $bucket)
{
  var_dump($bucket);
}

keyとsecretは内緒です。

上記プログラムを実行します。

php s3_listBuckets_example.php

結果

array(2) {
  ["ID"]=>
  string(64) "XXXXXXXXXXXXXXXXXXXX"
  ["DisplayName"]=>
  string(8) "mitsugeek"
}
array(1) {
  [0]=>
  array(2) {
    ["Name"]=>
    string(13) "mitsugeek.net"
    ["CreationDate"]=>
    string(24) "2013-03-28T13:58:27.000Z"
  }
}
string(16) "XXXXXXXXX"

以上で、S3のバケット一覧取得まで確認しました。

参考

PHPで形態素解析エンジンのmecabを動かす。〜「私は貝柱になりたい。」を字句解析してみる〜

ということで、 twitterでliveコーディング(全然コーディングしてないじゃん。)しながら、 形態素解析エンジンのmecab動かすということを1人で黙々とやってる(現在進行形) そのときのサンプル。

<!DOCTYPE html>
<html>
<head>
  <title>形態素解析エンジンを試す</title>
  <meta charset="UTF-8">
</head>
<body>
<?php
$str = '私は貝柱になりたい。';
$str = mb_convert_encoding($str, "euc-jp", "utf-8");
$mecab = new Mecab();
$nodes = $mecab->parseToNode($str);
foreach($nodes as $node) {
        echo mb_convert_encoding($node->surface,"utf-8","euc-jp")."<br />\n";
}
?>
<body>
</html>

結果

<!DOCTYPE html>
<html>
<head>
  <title>形態素解析エンジンを試す</title>
  <meta charset="UTF-8">
</head>
<body>
<br /><br /><br />
貝柱<br /><br />
なり<br />
たい<br /><br />
<br />
<body>
</html>

サーバ側の結果はこちら→ http://mitsugeek.net/mecab/test.php ※申し訳ありませんが、いまは動いてません。。

以下は、インストールまでの流れ

HTML5のmuliple属性をつけた複数ファイルのアップロードをPHPで受け止めてみた。(メモ)

クライアント側。inputにmultiple属性をつけてるのとnameを配列にしている。

<form action="uplod.php" method="POST" enctype="multipart/form-data">
    <input type="file" name="file[]" multiple>
    <input type="submit" value="Upload" />
</form>

鯖側で$_FILEをログに吐いてみる。

Array
(
    [file] => Array
        (
            [name] => Array
                (
                    [0] => Penguins.jpg
                    [1] => Tulips.jpg
                )

            [type] => Array
                (
                    [0] => image/jpeg
                    [1] => image/jpeg
                )

            [tmp_name] => Array
                (
                    [0] => /tmp/phpV8xnID
                    [1] => /tmp/phpsS56kp
                )

            [error] => Array
                (
                    [0] => 0
                    [1] => 0
                )

            [size] => Array
                (
                    [0] => 777835
                    [1] => 620888
                )

        )

)

PHPで受け止める。

<?php
while(list($key,$value) = each($_FILES['file']['name']))
{
    $file_name = $_FILES['name'][$key];
    $file_tmp_name = $_FILES['tmp_name'][$key];
    $file_size = $_FILES['size'][$key];
    $file_error = $_FILES['error'][$key];
}

ループでまわしている中でmove_uploaded_fileを行えば複数保存が可能。

chromeとfirefoxとIEで試してみました。
IEではファイルはひとつしか選択できませんでした。