使用 AJAX、PHP 和 jQuery 上传多张图片
Posted
技术标签:
【中文标题】使用 AJAX、PHP 和 jQuery 上传多张图片【英文标题】:Upload multiple image using AJAX, PHP and jQuery 【发布时间】:2015-05-05 13:48:46 【问题描述】:我在使用 AJAX 上传多张图片时遇到很多问题。我写了这段代码:
HTML
<form id="upload" method="post" enctype="multipart/form-data">
<div id="drop" class="drop-area">
<div class="drop-area-label">
Drop image here
</div>
<input type="file" name="file" id="file" multiple/>
</div>
<ul class="gallery-image-list" id="uploads">
<!-- The file uploads will be shown here -->
</ul>
</form>
<div id="listTable"></div>
jQuery/AJAX
$(document).on("change", "input[name^='file']", function(e)
e.preventDefault();
var This = this,
display = $("#uploads");
// list all file data
$.each(This.files, function(i, obj)
// for each image run script asynchronous
(function(i)
// get data from input file
var file = This.files[i],
name = file.name,
size = file.size,
type = file.type,
lastModified = file.lastModified,
lastModifiedDate = file.lastModifiedDate,
webkitRelativePath = file.webkitRelativePath,
slice = file.slice,
i = i;
// DEBUG
/*
var acc = []
$.each(file, function(index, value)
acc.push(index + ": " + value);
);
alert(JSON.stringify(acc));
*/
$.ajax(
url:'/ajax/upload.php',
contentType: "multipart/form-data",
data:
"image":
"name":name,
"size":size,
"type":type,
"lastModified":lastModified,
"lastModifiedDate":lastModifiedDate,
"webkitRelativePath":webkitRelativePath,
//"slice":slice,
,
type: "POST",
// Custom XMLHttpRequest
xhr: function()
var myXhr = $.ajaxSettings.xhr();
// Check if upload property exists
if(myXhr.upload)
// For handling the progress of the upload
myXhr.upload.addEventListener("progress",progressHandlingFunction, false);
return myXhr;
,
cache: false,
success : function(data)
// load ajax data
$("#listTable").append(data);
);
// display progress
function progressHandlingFunction(e)
if(e.lengthComputable)
var perc = Math.round((e.loaded / e.total)*100);
perc = ( (perc >= 100) ? 100 : ( (perc <= 0) ? 0 : 0 ) );
$("#progress"+i+" > div")
.attr("aria-valuenow":perc)
.css("width", perc+"%");
// display list of files
display.append('<li>'+name+'</li><div class="progress" id="progress'+i+'">'
+'<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">'
+'</div></div>');
)(i);
);
);
我尝试了各种版本,但从未成功通过 ajax 发送多个数据。我已经以这种方式尝试了您在上面看到的内容,现在我只得到 POST 信息。我明白为什么我会收到 POST,但我需要发送 FILES 信息,但我不知道我错在哪里。
我不是第一次使用 ajax,并且经常将它用于大多数项目,但我从来没有发送过多个文件,现在这让我很困扰。
谢谢!
【问题讨论】:
请澄清: 1. contentType 是multipart/form-data
而data 不是(jQuery.param 会将js 对象转换为x-www-form-urlencoded
而不是),所以数据会在翻译中丢失。您要转移什么以及如何转移? 2. 没有上传实际图片数据,这是故意的吗? 3. 每个文件调用一个ajax,导致处理过程中的大量连接和冲突,这是故意的吗? 4. 我没有看到任何拖放代码。你想要吗?
【参考方案1】:
尝试利用json
上传,处理file
对象
<div id="drop" class="drop-area ui-widget-header">
<div class="drop-area-label">Drop image here</div>
</div>
<br />
<form id="upload">
<input type="file" name="file" id="file" multiple="true" accepts="image/*" />
<ul class="gallery-image-list" id="uploads">
<!-- The file uploads will be shown here -->
</ul>
</form>
<div id="listTable"></div>
css
#uploads
display:block;
position:relative;
#uploads li
list-style:none;
#drop
width: 90%;
height: 100px;
padding: 0.5em;
float: left;
margin: 10px;
border: 8px dotted grey;
#drop.hover
border: 8px dotted green;
#drop.err
border: 8px dotted orangered;
js
var display = $("#uploads"); // cache `#uploads`, `this` at `$.ajax()`
var droppable = $("#drop")[0]; // cache `#drop` selector
$.ajaxSetup(
context: display,
contentType: "application/json",
dataType: "json",
beforeSend: function (jqxhr, settings)
// pre-process `file`
var file = JSON.parse(
decodeURIComponent(settings.data.split(/=/)[1])
);
// add `progress` element for each `file`
var progress = $("<progress />",
"class": "file-" + (!!$("progress").length
? $("progress").length
: "0"),
"min": 0,
"max": 0,
"value": 0,
"data-name": file.name
);
this.append(progress, file.name + "<br />");
jqxhr.name = progress.attr("class");
);
var processFiles = function processFiles(event)
event.preventDefault();
// process `input[type=file]`, `droppable` `file`
var files = event.target.files || event.dataTransfer.files;
var images = $.map(files, function (file, i)
var reader = new FileReader();
var dfd = new $.Deferred();
reader.onload = function (e)
dfd.resolveWith(file, [e.target.result])
;
reader.readAsDataURL(new Blob([file],
"type": file.type
));
return dfd.then(function (data)
return $.ajax(
type: "POST",
url: "/echo/json/",
data:
"file": JSON.stringify(
"file": data,
"name": this.name,
"size": this.size,
"type": this.type
)
,
xhr: function ()
// do `progress` event stuff
var uploads = this.context;
var progress = this.context.find("progress:last");
var xhrUpload = $.ajaxSettings.xhr();
if (xhrUpload.upload)
xhrUpload.upload.onprogress = function (evt)
progress.attr(
"max": evt.total,
"value": evt.loaded
)
;
xhrUpload.upload.onloadend = function (evt)
var progressData = progress.eq(-1);
console.log(progressData.data("name")
+ " upload complete...");
var img = new Image;
$(img).addClass(progressData.eq(-1)
.attr("class"));
img.onload = function ()
if (this.complete)
console.log(
progressData.data("name")
+ " preview loading..."
);
;
;
uploads.append("<br /><li>", img, "</li><br />");
;
return xhrUpload;
)
.then(function (data, textStatus, jqxhr)
console.log(data)
this.find("img[class=" + jqxhr.name + "]")
.attr("src", data.file)
.before("<span>" + data.name + "</span><br />");
return data
, function (jqxhr, textStatus, errorThrown)
console.log(errorThrown);
return errorThrown
);
)
);
$.when.apply(display, images).then(function ()
var result = $.makeArray(arguments);
console.log(result.length, "uploads complete");
, function err(jqxhr, textStatus, errorThrown)
console.log(jqxhr, textStatus, errorThrown)
)
;
$(document)
.on("change", "input[name^=file]", processFiles);
// process `droppable` events
droppable.ondragover = function ()
$(this).addClass("hover");
return false;
;
droppable.ondragend = function ()
$(this).removeClass("hover")
return false;
;
droppable.ondrop = function (e)
$(this).removeClass("hover");
var image = Array.prototype.slice.call(e.dataTransfer.files)
.every(function (img, i)
return /^image/.test(img.type)
);
e.preventDefault();
// if `file`, file type `image` , process `file`
if (!!e.dataTransfer.files.length && image)
$(this).find(".drop-area-label")
.css("color", "blue")
.html(function (i, html)
$(this).delay(3000, "msg").queue("msg", function ()
$(this).css("color", "initial").html(html)
).dequeue("msg");
return "File dropped, processing file upload...";
);
processFiles(e);
else
// if dropped `file` _not_ `image`
$(this)
.removeClass("hover")
.addClass("err")
.find(".drop-area-label")
.css("color", "darkred")
.html(function (i, html)
$(this).delay(3000, "msg").queue("msg", function ()
$(this).css("color", "initial").html(html)
.parent("#drop").removeClass("err")
).dequeue("msg");
return "Please drop image file...";
);
;
;
php
<?php
if (isset($_POST["file"]))
// do php stuff
// call `json_encode` on `file` object
$file = json_encode($_POST["file"]);
// return `file` as `json` string
echo $file;
;
jsfiddle http://jsfiddle.net/guest271314/0hm09yqo/
【讨论】:
问题,在 PHP 中,字符串$file
我用于处理数据并且可以像使用 $_FILE[]
一样上传?
@IvijanStefanStipić 不客气:) $file
php
部分在帖子 not 与 $_FILES
相同。 $_FILES
似乎需要 <form>
元素,带有 enctype="multipart/form-data"
属性。 post方法利用JSON
数据类型post,处理响应。见php.net/manual/en/features.file-upload.post-method.php、w3.org/TR/html401/interact/forms.html#h-17.13.4.2、sitepoint.com/handle-file-uploads-php、***.com/questions/3586919/…。
我问是因为我想调整图像大小、重命名、制作拇指并保存在文件夹中。我会看看这个链接并尝试。再次感谢。
@IvijanStefanStipić 实际图像应该是data-uri
developer.mozilla.org/en-US/docs/Web/HTTP/data_URIsfile.file
,图像名称file.name
。以上是关于使用 AJAX、PHP 和 jQuery 上传多张图片的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 php jquery ajax 上传文件和插入数据