■default ---■fontsize --70% --80% --100% --120% --140% --- --■scroll_switch

web上のPHPから共有フォルダにファイルをコピーする

web上のPHPから共有フォルダにファイルをコピーする


HTMLを使ってウェブサーバーから同じLANに接続されているパソコンの共有フォルダに
ファイルをコピーしようとしたのですが、超絶つまったので記録しておきます。
--------------------------
■状況
パソコンA(共有フォルダのあるパソコン,固定IP,Windows、英語)
パソコンB(webサーバー、Apache2+PHP5,固定IP,Windows)
パソコンC(クライアント,固定IP,Windows)

CからBにファイルをアップロードする場合はWEBクライアントから普通にできます。
C→B OK
Cから手動でBの共有フォルダにファイルをコピーするのも普通。
C→A OK
Bのサーバーをパソコンとして操作してBの共有フォルダにファイルコピーも普通にできます。
B→A OK
でも、Cから操作してBにあるファイルをAにcopyしようとするとNG
C→B→X A NG

ちなみに何でこんな事をしたいかというとAにホットフォルダで動くプログラムがあるからです。
それをブラウザ上で動かしたいからです。
--------------------------
//PHPはこんな感じ
$moto = "aaa.txt";
$saki = "//192.168.1.1/share/aaa.txt";
copy($moto,$saki);
--------------------------
そうするとこんなエラーが出ます。
failed to open stream: Permission denied
パーミッションがダメです。みたいな。

で、まず行った事は、ウインドウズの昨日にネットワークドライブというのがあるので、
それを設定してみました。

$saki = "n:/share/aaa.txt";
みたいに普通のパスっぽくなるので、同かなと思いましたがNG。
しかも、調べてみると「ネットワークドライブはつかえねー」みたいなことが書いてあったので、終了。
failed to open stream: No such file or directory
確かに共有フォルダが見つかりもしていません。

ちなみに何故通過しないかというと、webクライアントからのアクセスだと「管理者権限」が切れているかららしいです。

次に試したのは、パーミッションNGとなっていますので、Aの共有フォルダのセキュリティ設定をゆるゆるにする。
ネットで調べてユーザー権限とか共有フォルダのセキュリティー設定とかいろいろ変えてみましたが、ダメ。
ゲストを有効にしてもダメ。
アノニマスとかサクラマスとか言うので、俺はニジマス派だっ、といってやりました。
しかも、OSが英語で、キーボードもおもちゃみたいなやつで、イラついてやめました。
しかも、そんなに勝手に設定変更するとよくないパソコンなので、やめました。

共有フォルダのパスを指定する時にパスワードとかくっつけて指定する方法がPHPならもしやあるのでは無いかと思いましたが、私のサーチ能力では見つかりませんでした。

それではここから解決編です。
--------------------------
■解決編
やり方の概要は「バッチファイルでコピーする」
順番で行くとこのようになります。

1.Cの操作画面で何らかのボタンを押す
2.BのPHPで1で指定されたファイルをコピーするバッチファイルを書き出す
3.BのPHPで2で作ったバッチファイルを実行する
以上。
で、いいと思ったのですが、PHPから動かしたバッチファイルはなんか違う人が動かしたってことになり、また「管理者権限」が外れるらしく、共有フォルダにアクセスできません。
そこで、もう人手間必要になります。
タスクスケジューラーを使って管理者権限で動かす。
タスクスケジューラーは別にスケジュールで動かすためだけにあるんじゃない。と本人も主張しているに違い有りません。

前準備
1.Bのサーバーのタスクスケジューラーにタスクを登録する
実行
1.Cの操作画面で何らかのボタンを押す
2.BのPHPで1で指定されたファイルをコピーするバッチファイルを書き出す
3.BのPHPで2で作ったバッチファイルを動かすタスクスケジュールを実行する
これでできるようになりました。
C→B→タスクスケジューラー→バッチファイル→バッチコマンド→A
です。
-------------------------
■具体的なやり方
バッチファイルの名前が固定になってしまうので、複数アクセスとかがあると、挙動不審になると思いますが、とりあえずできるようになりました。
「1.タスクスケジューラーにタスクを登録する」
から説明します。
タスクスケジューラーの設定は2つだけすればOK。
・「操作」の「プログラム/スクリプト」で書き出す予定のバッチファイルのフルパスを指定してください(今回はd:/web/copy.batにします。)
・「全般」の「名前」で好きな名前を付けてください。もちろん半角英数の方がいいです。(今回はsendにします。)

タスクスケジューラーの立ち上げ方はこちらを参考にして下さい。
+=http://50pooh.blogspot.jp/2010/06/vista-windows-7everythingexe.html
注意点としてバッチファイルのパスの記述では""で囲ってはいけません。

チェックする設定は2個です。
・ユーザーがログオンしているかどうかに関わらず実行する。
・最上位の特権で実行する
設定方法はこちらを参考にして下さい。
+=http://www.atmarkit.co.jp/ait/articles/1307/08/news101.html

今回のミソはこの「・最上位の特権で実行する」というところに有り、なんかバグみたいな裏技ですが、タスクスケジューラーを一回通すと管理者権限にできるみたいな。
有名人の友達だから顔パスみたいな。
後ろにぴったりくっついて改札を抜けるみたいな。
感じです。
念のために書いておきますが、間違ってもスケジュールみたいなのは登録しないようにしてください。
あと、cmd.exeみたいなコマンドプロントからの引数で指定とかしなくても、バッチファイル直指定で動きました。

前準備は以上です。
PHPのソースの方です。

$cd = 'copy "d:/web/aaa.txt" "//192.168.1.1/share/aaa.txt" \n';
$cd = str_replace("/","\\",$cd);
$fp = fopen("copy.bat", 'w');
fwrite($fp, $cd);
shell_exec("schtasks.exe /run /tn send");

1行目はバッチファイルの中身です。
なので、コピー先とかファイルとかは適材適所にして下さい。
複数copyしたい時は連続で書けばOKですし、変数で変えていただいてもOK
スペースを含むフォルダがあるかもしれないので、""で囲っておいたほうがいいと思います。
''シングルクオーテーションではダメです。
コピー元(初めに書いてあるパス)の方はタスクスケジューラーから見た場合なので、相対パスではいけません。
絶対パスにして下さい。
コピー先の共有フォルダのほうですが、今回はIPアドレスで書いて有りますが、いわゆる「ネットワークコンピューター」で出るアドレスであれば大丈夫なようです。

バッチファイルの書き方などはこちらなどを参考にして下さい。
+=http://ykr414.com/dos/dos02.html

2行目は\マークが見づらいから、書き換えてるだけなので意味は有りません。
1行目を初めから\\で書いておけばOKです。

3行目と4行目でバッチファイルを作ります。
これも場所とか好きな所を指定してください。
パスを指定しないとPHPファイルのあるカレントフォルダになります。
実際はファイルロックとかエラー処理とか加えてください。
バッチファイルは使い捨てなので処理が終わった後消しても消さなくてもいいですが、お任せします。
当然ですが、ここで作られたバッチファイルをダブルクリックすればAの共有フォルダに対象ファイルがコピーされます。
一回動作確認したほうがいいかもしれません。
タスクスケジューラーを起動してそっちの「再生ボタン」みたいなのも押してテストしたほうがいいかもしれません。

5行目でタスクスケジューラーをキック。
タスクスケジューラーの実行ファイルが「schtasks.exe」だなんてことはどこで調べればいいのやら分かりませんが、これで動きます。
変更するのは send の部分だけです。前準備で登録した名前にして下さい。
関数は
system() とか shell_exec() とか exec()
ありますが、どれがいいのかはよく分かりません。
shell_execで動いたのでとりあえずこれを使っています。
-----------------------------------
使い捨てのコマンドは別にバッチファイルじゃなくても、
JSでも何でもいいでしょうし、
操作も、フォルダ作成とか共有フォルダ内の閲覧とか、できると思います。

ポイントはタスクスケジューラーをかませるという事です。
あと、タスクスケジューラーはログオンして無くても動かせるという事を発見しました。

どこの馬の骨か分からないやつは一回偉い人に話を通してもらわないと、何もできないという事の教訓です。
セーラームーンも月に代わってるから、おしおきできるのです。

スポンサーサイト
ブログ内検索ワード
マジック / フラリッシュ / デザイン / ~のコツ / プログラム関連 /