jQuery HTML5多文件上传:通过AJAX一一上传
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13656066/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTML5 multiple file upload: upload one by one through AJAX
提问by Mark
I have a multiple files upload form:
我有一个多文件上传表单:
<input type="file" name="files" multiple />
I am posting these files with ajax. I would like to upload the selected files one by one (to create individual progress bars, and out of curiousity).
我正在用 ajax 发布这些文件。我想一一上传选定的文件(为了创建单独的进度条,出于好奇)。
I can get the list of files or individual files by
我可以通过以下方式获取文件列表或单个文件
FL = form.find('[type="file"]')[0].files
F = form.find('[type="file"]')[0].files[0]
yieling
夷陵
FileList { 0=File, 1=File, length=2 }
File { size=177676, type="image/jpeg", name="img.jpg", more...}
But FileList is immutable and I can't figure out how to submit the single file.
但是 FileList 是不可变的,我不知道如何提交单个文件。
I think this is possible as I saw http://blueimp.github.com/jQuery-File-Upload/. I don't want to use this plugin however as it's as much about learning as the result (and it would need too much custimizing anyway). I also don't want to use Flash.
我认为这是可能的,因为我看到了http://blueimp.github.com/jQuery-File-Upload/。然而,我不想使用这个插件,因为它与学习和结果一样多(无论如何它都需要太多的自定义)。我也不想使用 Flash。
回答by pocesar
For this to be a synchronous operation, you need to start the new transfer when the last one is done. Gmail, for example, send everything at once, concurrently.
The event for the progress on AJAX file upload is progress
or onprogress
on the raw XmlHttpRequest
instance.
为了使这成为一个同步操作,您需要在最后一个传输完成后开始新的传输。例如,Gmail 会同时发送所有内容。AJAX 文件上传进度的事件是progress
或onprogress
在原始XmlHttpRequest
实例上。
So, after each $.ajax()
, on the server side (which I don't know what you'll be using), send a JSON response to execute the AJAX on the next input. One option would to bind the AJAX element to each element, to make things easier, so you could just do, in the success
the $(this).sibling('input').execute_ajax()
.
因此,在每个 之后$.ajax()
,在服务器端(我不知道您将使用什么),发送一个 JSON 响应以在下一个输入上执行 AJAX。一种选择是将 AJAX 元素绑定到每个元素,以简化操作,因此您可以success
在$(this).sibling('input').execute_ajax()
.
Something like this:
像这样的东西:
$('input[type="file"]').on('ajax', function(){
var $this = $(this);
$.ajax({
'type':'POST',
'data': (new FormData()).append('file', this.files[0]),
'contentType': false,
'processData': false,
'xhr': function() {
var xhr = $.ajaxSettings.xhr();
if(xhr.upload){
xhr.upload.addEventListener('progress', progressbar, false);
}
return xhr;
},
'success': function(){
$this.siblings('input[type="file"]:eq(0)').trigger('ajax');
$this.remove(); // remove the field so the next call won't resend the same field
}
});
}).trigger('ajax'); // Execute only the first input[multiple] AJAX, we aren't using $.each
The above code would be for multiple <input type="file">
but not for <input type="file" multiple>
, in that case, it should be:
上面的代码将用于 multiple<input type="file">
而不是 for <input type="file" multiple>
,在这种情况下,它应该是:
var count = 0;
$('input[type="file"]').on('ajax', function(){
var $this = $(this);
if (typeof this.files[count] === 'undefined') { return false; }
$.ajax({
'type':'POST',
'data': (new FormData()).append('file', this.files[count]),
'contentType': false,
'processData': false,
'xhr': function() {
var xhr = $.ajaxSettings.xhr();
if(xhr.upload){
xhr.upload.addEventListener('progress', progressbar, false);
}
return xhr;
},
'success': function(){
count++;
$this.trigger('ajax');
}
});
}).trigger('ajax'); // Execute only the first input[multiple] AJAX, we aren't using $.each
回答by Nathan Kot
This looks like a very good tutorial, just what you're looking for.
That noted, uploading via vanilla ajax isn't supported in all browsers, and I would still recommend using an iframe
. (I.E dynamically create an iframe and POST it using javascript)
需要注意的是,并非所有浏览器都支持通过 vanilla ajax 上传,我仍然建议使用iframe
. (IE 动态创建一个 iframe 并使用 javascript 发布它)
I have always been using this scriptand I find it very concise. If you want to learn how to upload via creating an iframe, you should dig through it's source.
我一直在使用这个脚本,我觉得它非常简洁。如果你想学习如何通过创建 iframe 上传,你应该挖掘它的源代码。
Hope it helps :)
希望能帮助到你 :)
Extra edit
额外编辑
To create progress bars with the iframe method, you will need to do some work server-side. If you're using php, you can use:
要使用 iframe 方法创建进度条,您需要在服务器端做一些工作。如果您使用的是 php,则可以使用:
- Session upload progressfor php5.4+
- Upload progress packagefor php<5.4
If use nginx you can also choose to compile with their Upload progress module
如果使用 nginx 你也可以选择使用他们的上传进度模块进行编译
All of these work the same way - every upload has a UID, you will request for the 'progress' associated with that ID at consistent intervals via ajax. This will return the upload progress as determined by the server.
所有这些都以相同的方式工作 - 每个上传都有一个 UID,您将通过 ajax 以一致的时间间隔请求与该 ID 关联的“进度”。这将返回由服务器确定的上传进度。
回答by hluchjak
I was facing same problem and came with this solution. I simply retrieve form with multipart, and in recursive call ( file after file ) start ajax request, which only calls next when is done.
我遇到了同样的问题,并提供了这个解决方案。我只是用 multipart 检索表单,并在递归调用(文件后文件)中启动 ajax 请求,它只在完成时调用 next 。
var form = document.getElementById( "uploadForm" );
var fileSelect = document.getElementById( "photos" );
var uploadDiv = document.getElementById( "uploads" );
form.onsubmit = function( event ) {
event.preventDefault( );
var files = fileSelect.files;
handleFile( files, 0 );
};
function handleFile( files, index ) {
if( files.length > index ) {
var formData = new FormData( );
var request = new XMLHttpRequest( );
formData.append( 'photo', files[ index ] );
formData.append( 'serial', index );
formData.append( 'upload_submit', true );
request.open( 'POST', 'scripts/upload_script.php', true );
request.onload = function( ) {
if ( request.status === 200 ) {
console.log( "Uploaded" );
uploadDiv.innerHTML += files[ index ].name + "<br>";
handleFile( files, ++index );
} else {
console.log( "Error" );
}
};
request.send( formData );
}
}
回答by Milan Krushna
Using this source code you can upload multiple file like google one by one through ajax. Also you can see the uploading progress
使用此源代码,您可以通过ajax 一一上传多个文件,例如google。也可以看到上传进度
HTML
HTML
<input type="file" id="multiupload" name="uploadFiledd[]" multiple >
<button type="button" id="upcvr" class="btn btn-primary">Start Upload</button>
<div id="uploadsts"></div>
Javascript
Javascript
<script>
function uploadajax(ttl,cl){
var fileList = $('#multiupload').prop("files");
$('#prog'+cl).removeClass('loading-prep').addClass('upload-image');
var form_data = "";
form_data = new FormData();
form_data.append("upload_image", fileList[cl]);
var request = $.ajax({
url: "upload.php",
cache: false,
contentType: false,
processData: false,
async: true,
data: form_data,
type: 'POST',
xhr: function() {
var xhr = $.ajaxSettings.xhr();
if(xhr.upload){
xhr.upload.addEventListener('progress', function(event){
var percent = 0;
if (event.lengthComputable) {
percent = Math.ceil(event.loaded / event.total * 100);
}
$('#prog'+cl).text(percent+'%')
}, false);
}
return xhr;
}
})
.success(function(res,status) {
if(status == 'success'){
percent = 0;
$('#prog'+cl).text('');
$('#prog'+cl).text('--Success: ');
if(cl < ttl){
uploadajax(ttl,cl+1);
}else{
alert('Done ');
}
}
})
.fail(function(res) {
alert('Failed');
});
}
$('#upcvr').click(function(){
var fileList = $('#multiupload').prop("files");
$('#uploadsts').html('');
var i
for ( i = 0; i < fileList.length; i++) {
$('#uploadsts').append('<p class="upload-page">'+fileList[i].name+'<span class="loading-prep" id="prog'+i+'"></span></p>');
if(i == fileList.length-1){
uploadajax(fileList.length-1,0);
}
}
});
</script>
PHP
PHP
upload.php
move_uploaded_file($_FILES["upload_image"]["tmp_name"],$_FILES["upload_image"]["name"]);
回答by Shreyas
Html Code
html代码
<div class="row">
<form id="singleUploadForm" name="singleUploadForm" style="float: right; padding-right: 25px">
<input style="float: left;" id="singleFileUploadInput" type="file" name="files" class="file-input btn btn-default" required multiple/>
<button style="float: left" type="submit" class="btn .btn-primary">Upload</button>
</form>
</div>
JavaScript Code
JavaScript 代码
$('#mutipleUploadForm').submit(function (event) {
var formElement = this;
var formData = new FormData(formElement);
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: "/uploadFile",
data: formData,
processData: false,
contentType: false,
success: function (response) {
alert("Image Uploaded Successfully");
location.reload();
},
error: function (error) {
console.log(error);
// process error
}
});
event.preventDefault();
});
Spring Controller Class
弹簧控制器类
@PostMapping("/uploadFile")
@ResponseBody
public boolean uploadMutipleFiles(@RequestParam("file") MultipartFile[] file) {
List<Boolean> uploadStatusList = new ArrayList<>();
for (MultipartFile f : file) {
uploadStatusList.add(uploadFile(f));
}
return !uploadStatusList.contains(false);
}
public boolean uploadFile(@RequestParam("file") MultipartFile file) {
boolean uploadStatus = galleryService.storeFile(file);
return uploadStatus;
}
Spring Service Class
Spring 服务类
public boolean storeFile(MultipartFile file) {
boolean uploadStatus = false;
try {
String fileName = file.getOriginalFilename();
InputStream is = file.getInputStream();
Files.copy(is, Paths.get(imagesDirectory + fileName), StandardCopyOption.REPLACE_EXISTING);
System.out.println("File store success");
uploadStatus = true;
} catch (Exception e) {
e.printStackTrace();
}
return uploadStatus;
}