【问题标题】:Javascript XMLHttpRequest upload file with POST data带有POST数据的Javascript XMLHttpRequest上传文件
【发布时间】:2018-07-19 06:08:21
【问题描述】:

我正在尝试使用拖放在 JavaScript 中创建小型上传。我已经编写了代码,但它似乎不起作用。目前网站的工作方式,上传脚本必须为网站提供PHPSESSID等信息,服务器处理请求的附加数据和文件本身。如果用户删除了多个文件,脚本应该一个一个地上传所有文件。但是目前我什至无法让 JavaScript 上传一个文件。在调试工具中查看时,服务器响应的是网站本身,而不是用于文件上传的响应。

在旧版本代码上使用现有表单上传文件时,我注意到在发送文件内容之前来自网络浏览器的请求如下所示:

Content-Disposition: form-data; name="file"; filename="file.txt"
Content-Type: text/plain

但是,当使用我使用的脚本发送时,我只看到了这个:

Content-Disposition: form-data; name="file"

但是我不确定代码有什么问题,也找不到任何有用的东西来解决这个问题。

我不想使用额外的库,例如 JQuery 或类似的东西

Javascript 代码:

function drop(e){
    e.preventDefault();
    if(e.dataTransfer.items){
        for(var i=0; i < e.dataTransfer.items.length; i++){
            var reader = new FileReader();
            var req = new XMLHttpRequest();
            var f = e.dataTransfer.files[i]
            req.onprogress = function(e){
                if (e.lengthComputable){
                    console.log("progress: " + e.loaded / e.total);
                }
            }
            req.open("POST", document.location, true);
            req.setRequestHeader("Content-Type", "application/octet-stream");
            reader.onload = function(e){
                var fd = new FormData();
                fd.append("PHPSESSID", document.cookie.split("=")[1]);
                fd.append("request", JSON.stringify({"command":"upload", "path":path + f.name, "path-type":pathtype}))
                fd.append("file", e.target.result);
                req.send(fd);
            }
            reader.readAsBinaryString(e.dataTransfer.items[i].getAsFile());
        }
    }else{
        for(var i=0; i < e.dataTransfer.files.length; i++){
            console.log(e.dataTransfer.files[i]);
        }
    }
}

负责上传的 PHP 代码:

if(isset($_POST['request'])){
    $request = json_decode($_POST['request'], true);
    if($request['command'] == "upload"){
        if(isset($request['path']) && isset($request['path-type'])){
            $path = "";
            if($request['path-type'] === "private"){
                $path = truepath($private_dir . $request['path']);
                if(!(substr($path, 0, strlen($private_dir)) === $private_dir)){
                    die();
                }
            }elseif($request['path-type'] === "public"){
                $path = truepath($public_dir . $request['path']);
                if(!(substr($path, 0, strlen($public_dir)) === $public_dir)){
                    die();
                }
            }else{
                die();
            }
            move_uploaded_file($_FILES["file"]["tmp_name"], $path);
            die();
        }
    }
    die();
}

【问题讨论】:

    标签: javascript php file-upload


    【解决方案1】:

    经过几天的实验,我发现这在服务器端失败的原因是因为$_POST$_FILES 不是由代码设置的。

    代码失败的原因有多种,都是 JavaScript 方面的原因。

    需要改变的地方:

    1. FileReader 完全没有必要。
    2. req.setRequestHeader("Content-Type", "application/octet-stream"); 不正确,因为它应该是“multipart/form-data”。除此之外,不应设置它,因为它会破坏内容类型标题。这是因为在上传文件时,Content-Type 标头也包含边界,这是由浏览器生成的。当您设置Content-Type 时,您将覆盖浏览器为文件上传生成的任何内容。 I was able to find this out thanks to this answer.

    PHP 方面的代码(令人惊讶)是正确的。 JavaScript 的最新代码是:

    function drop(e){
        e.preventDefault();
        if(e.dataTransfer.files){
            for(var i=0; i < e.dataTransfer.files.length; i++){
                var req = new XMLHttpRequest();
                var f = e.dataTransfer.files[i]
                req.onprogress = function(e){
                    if (e.lengthComputable){
                        console.log("progress: " + e.loaded / e.total);
                    }
                }
                req.open("POST", document.location, true);
                req.overrideMimeType('application/octet-stream')
                var fd = new FormData();
                fd.append("PHPSESSID", document.cookie.split("=")[1]);
                fd.append("request", JSON.stringify({"command":"upload", "path":path + f.name, "path-type":pathtype}))
                fd.append("file", f);
                req.send(fd);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-21
      • 1970-01-01
      • 2021-03-26
      • 2019-10-16
      • 1970-01-01
      • 2012-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多