我正在尝试使用拖放功能在JavaScript中创建小型上传。我编写了代码,但它似乎没有用。当前网站的工作方式,上传脚本必须为网站提供PHPSESSID
等信息,服务器处理请求的附加数据以及文件本身。如果用户删除多个文件,脚本应该逐个上传所有文件。目前我甚至无法让JavaScript上传一个文件。查看调试工具时,服务器正在响应网站本身,而不是用于文件上传的响应。
在较旧版本的代码上使用现有表单上传文件时,我注意到在发送文件内容之前来自Web浏览器的请求如下所示:
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();
}
答案 0 :(得分:1)
经过几天的实验,我发现服务器端失败的原因是因为代码没有设置$_POST
和$_FILES
。
代码失败的原因有很多,都是由JavaScript方面引起的。
需要改变的事情:
FileReader
完全没必要。req.setRequestHeader("Content-Type", "application/octet-stream");
不正确,因为它应该是&multi39 / form-data&#39;。除此之外,它不应该被设置,因为它将破坏内容类型标题。这是因为在上传文件时,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);
}
}
}