41107
よろしくお願いします。  
簡易ファイルサーバを作っています。  
ファイルのアップロードについて、formの<input type = "file">を使ってのアップロードはできています。  
ドラッグ&ドロップでもファイルをアップロードする機能を付けたいと思っているのですが、質問があります。

色々なサイトを参考に、ドラッグ&ドロップされたファイルの名前を取得できるのは確認しました。

しかしながらperlで書いたCGIに渡すにも、  
$q->tmpFileName($q->param('files'));  
でテンポラリファイル名を取得できません。  
まあ、実際にテンポラリファイルをアップロードしていないので当たり前ですよね。

ドラッグ&ドロップされたファイルをサーバにアップロードするにはどのようにすればいいでしょうか?  
javascript側・perl側、お教え下さい。

・2018.1.22 追記  
ご回答ありがとうございます。プログラムを修正したのですが、動きません。  
とりあえず、ファイルのアップロード機能は省いて、取得したファイル名をレスポンスに表示してみようと思ったのですが…。

・2018.1.24 追記  
いただいた追記を元に修正したのですが、今度は onload 自体動いていないようです。デフォルトの挙動をします。  
変更点は、  
・<script src="http://code.jquery.com/jquery-1.12.4.js"></script> を追加  
・'PUT' → 'POST' に  
・<body>タグの最後で  
<script type="text/javascript">  
$(function(){  
PageLoad();  
});  
</script>  
です。

・2018.1.26 追記。  
以下のコードでファイルをアップロードすることができました。  
ありがとうございます。

一つ質問があります。  
複数ファイルのドラッグ&ドロップの実装はどうしたらいいでしょうか?  
@files = $q->param('file');  
で複数のファイル名を取得できますが、  
$fp = $q->upload('file')  
は1ファイルだけの気が…。

```

    #!/usr/bin/perl
    use strict;
    use utf8;
    use CGI;
    use URI::Escape;
    use File::Basename;
    use File::Copy;
    use File::Path;
    use Encode;
    use FindBin;
    
    my $q = new CGI;
    my $fp = $q->upload('file');
    my @fnames = $q->param('file');
    foreach my $fname(@fnames){
        $fname = basename($fname);
        copy($fp, "./test/$fname");
    }
    my $out = <<'EOM';
    Content-type: text/html
    
    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    
    <script src="http://code.jquery.com/jquery-1.12.4.js"></script>
    <script type="text/javascript">
        function PageLoad(e) {
            alert("hoge");
            var dropFrame = document.getElementById('DropFrame');
            dropFrame.addEventListener('dragover', onDragOver, false);
            dropFrame.addEventListener('drop', onDrop, false);
        }
        function onDragOver(e){
            e.preventDefault();
        }
    
        function onDrop(e) {
            e.stopPropagation();
            e.preventDefault();
    
            var files = e.dataTransfer.files; 
    
            uploadFile(files[0]);
        }
        function uploadFile(file){
            var formData = new FormData();
            formData.append('file', file);
            $.ajax({
                async: true,
                type: 'POST',
                contentType: false,
                processData: false,
                url: 'dndtest.cgi',
                data: formData,
                dataType :'html'
            }).done(function(){});
        }
    </script>
    </head>
    <body>
        <div id="DropFrame" style="background-color:#b8deff;border:solid 1px #3470ff; width:360px; height:120px;">ここにファイルをドロップします。<br />$files</div>
    <script type="text/javascript">
        $(function(){
            PageLoad();
        });
    </script>\
    </body>
    </html>
    EOM
    print(encode('UTF-8', $out)) or die($!);
    
```

所々にalert()を入れて動作確認したところ、どこでも表示されたので、Syntax Errorはないと思います。  
ドラッグエリアにファイルをドロップしたときは、そのファイルが直接ブラウザに表示されるデフォルトの挙動はしないので、イベントのフックはできていると思います。  
プログラムの最後の方の$filesが空文字のままです。  
POST先のurlを <http://www.google.co.jp/> に変えても、ドラッグ&ドロップで移動しません。

初歩的な部分で躓いていると思います。  
どうかよろしくお願いいたします。
CC BY-SA 3.0
2018-01-20T00:08:24.633
41102
2018-01-25T23:48:08.713
2018-01-25T23:48:08.713
9674
9674
question
javascript perl
ドラッグ&ドロップされたファイルをサーバにアップロードするには?
FormData オブジェクトを使うと良いかと

> ファイルのアップロードについて、formの<input type = "file">を使ってのアップロードはできています。

サーバ側は動いているようなので、perlのコードはそのまま使えると思います、`url: 'f.php'` をperlのURLに変更してください。  
（サンプルコードは、エラー処理とか複数ファイルのuploadは考慮していません。）

```

        function drop(e) {
            e.stopPropagation();
            e.preventDefault();
    
            var files = e.dataTransfer.files;
    
            fup(files[0]);
        }
        function fup(file) {
            var formData = new FormData();
            formData.append('file', file);
    
    //javascriptだけなら
    //        var up = new XMLHttpRequest();
    //        up.open("POST", "f.php", true);
    //        up.send(formData);
    
    //jqueryを使っているなら
            $.ajax({
                async: true,
                type: 'POST',
                contentType: false,
                processData: false,
                url: 'f.php',
                data: formData,
                dataType :'html'
            }).done(function(){});
        }
    
```

追記  
jqueryを使うなら、  
読み込み`<script src="http://code.jquery.com/jquery-1.12.4.js"></script>`  
の追加と `<body onload="PageLoad();">` のonloadを削除して

```

    $(function(){
        PageLoad();
    });
    
```

に変更しましょう。

**追記２** 、

```

    var formData = new FormData();
    formData.append('file', file);
    
```

は,動的に

`<input name='file' value=file>`  
を作っています。

`$q->param(name)`のnameは、`<input
name=`のnameで指定された名前をセットしなければならないので、formData.appendで指定したname値にあわせないと値を受け取れません。

jquery $.ajax 動作確認用 perl v5.8 サンプル`uptest.cgi`（PHPerの自分のために追記,Content-Type:
multipart/form-data; を$.ajaxが送っていることも確認）

```

    #!/usr/local/bin/perl
    use File::Basename;
    use File::Copy;
    use CGI;
    
    #転送最大サイズを設定
    $CGI::POST_MAX = 1024 * 100000; #100MB
    
    $q = new CGI;
    
    
    #クライアントにヘッダを送信
    print "Content-type: text/html\n\n";
    binmode STDOUT;
    
    
    #ファイルの転送のチェック
    if (!defined($filename) and $error = $q->cgi_error){
        print 'file size error<br>';
        exit;
    }
    
    my $fp = $q->upload('file');
    
    #ファイルの存在の確認
    my $fname = basename($q->param('file'));
    if ($fname eq "./"){
        print 'file error<br>';
        exit;
    }
    
    copy ($fp, "./test/file/$fname");
    undef $q;
    
    print "ok upload!";
    
    exit;
    
```

```

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <head>
        <script src="http://code.jquery.com/jquery-1.12.4.js"></script>
        <script type="text/javascript">
            function PageLoad(e) {
                var dropFrame = document.getElementById('DropFrame');
                dropFrame.addEventListener('dragover', onDragOver, false);
                dropFrame.addEventListener('drop', onDrop, false);
            }
            function onDragOver(e){
                e.preventDefault();
            }
    
            function onDrop(e) {
                e.stopPropagation();
                e.preventDefault();
    
                var files = e.dataTransfer.files;
    
                uploadFile(files[0]);
            }
            function uploadFile(file){
                var formData = new FormData();
                formData.append('file', file);
                $.ajax({
                    async: true,
                    type: 'POST',
                    contentType: false,
                    processData: false,
                    url: 'uptest.cgi',
                    data: formData,
                    dataType :'html'
                }).done(function(html){
                    alert(html);
                });
            }
            $(function(){
                PageLoad();
            });
        </script>
    </head>
    <body>
        <div id="DropFrame" style="background-color:#b8deff;border:solid 1px #3470ff; width:360px; height:120px;">ここにファイルをドロップします。<br />$files</div>
    </body>
    </html>
```
CC BY-SA 3.0
2018-01-20T08:30:41.527
41107
2018-01-24T05:24:04.083
2018-01-24T05:24:04.083
22793
22793
41102
answer