HTML5多文件上传:通过AJAX一一上传
Posted
技术标签:
【中文标题】HTML5多文件上传:通过AJAX一一上传【英文标题】:HTML5 multiple file upload: upload one by one through AJAX 【发布时间】:2012-11-19 07:32:24 【问题描述】:我有一个多文件上传表单:
<input type="file" name="files" multiple />
我正在使用 ajax 发布这些文件。我想一一上传选定的文件(创建单独的进度条,出于好奇)。
我可以通过
获取文件列表或单个文件FL = form.find('[type="file"]')[0].files
F = form.find('[type="file"]')[0].files[0]
屈服
FileList 0=File, 1=File, length=2
File size=177676, type="image/jpeg", name="img.jpg", more...
但是 FileList 是不可变的,我不知道如何提交单个文件。
我认为这是可能的,因为我看到了http://blueimp.github.com/jQuery-File-Upload/。但是我不想使用这个插件,因为它与学习一样多(无论如何它需要太多的定制)。我也不想用 Flash。
【问题讨论】:
【参考方案1】: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 代码
$('#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 控制器类
@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 服务类
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;
【讨论】:
【参考方案2】:使用此源代码,您可以像 google 一样上传多个文件 一个通过ajax。还可以看到上传进度
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
<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
upload.php
move_uploaded_file($_FILES["upload_image"]["tmp_name"],$_FILES["upload_image"]["name"]);
【讨论】:
【参考方案3】:我遇到了同样的问题并提出了这个解决方案。我只是用 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 );
【讨论】:
这不是被问到的。 OP 要求使用单独的进度条一一上传选定的文件。投反对票。【参考方案4】:要使这是一个同步操作,您需要在最后一个传输完成后开始新的传输。例如,Gmail 可以同时同时发送所有内容。
AJAX 文件上传进度事件是 progress
或 onprogress
在原始 XmlHttpRequest
实例上。
所以,在每个$.ajax()
之后,在服务器端(我不知道您将使用什么),发送一个 JSON 响应以在下一个输入时执行 AJAX。一种选择是将 AJAX 元素绑定到每个元素,以使事情变得更容易,因此您可以在 success
$(this).sibling('input').execute_ajax()
中这样做。
类似这样的:
$('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
上面的代码将用于多个<input type="file">
,但不适用于<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
【讨论】:
请注意,此代码适用于仅支持 FormData 和 XmlHttpRequest2 的真正现代浏览器,对旧浏览器没有破解 创建一个新的“表单”并使用(new FormData()).append('file', this.files[count])
逐个添加文件是我想要的,谢谢!
同意:网址在哪里?
它使用相同的 URL 进行发布请求。
是的,只要在url
属性上添加您需要的任何内容,因为当省略它时,它会使用当前 URL。请参阅 jQuery 文档以了解 api.jquery.com/jquery.ajax/#jQuery-ajax-settings【参考方案5】:
This looks like a very good tutorial, just what you're looking for.
请注意,并非所有浏览器都支持通过 vanilla ajax 上传,我仍然建议使用iframe
。 (即动态创建 iframe 并使用 javascript 发布)
I have always been using this script 我觉得它非常简洁。如果你想通过创建 iframe 来学习如何上传,你应该去挖掘它的源代码。
希望对你有帮助:)
额外修改
要使用 iframe 方法创建进度条,您需要在服务器端做一些工作。如果你使用的是php,你可以使用:
Session upload progress php5.4+ Upload progress package 用于 php如果使用nginx你也可以选择用他们的Upload progress module编译
所有这些都以相同的方式工作 - 每个上传都有一个 UID,您将通过 ajax 以一致的时间间隔请求与该 ID 关联的“进度”。这将返回服务器确定的上传进度。
【讨论】:
第一个链接确实是一个很好的关于 FormData 对象的教程,谢谢!以上是关于HTML5多文件上传:通过AJAX一一上传的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ASP.NET MVC 中处理 HTML5 多文件上传?
HTML5可预览多图片ajax上传(使用formData传递数据)