有人可以解释如何实现 jQuery 文件上传插件吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17934689/
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
Can someone explain how to implement the jQuery File Upload plugin?
提问by Austen
EDIT (Oct 2019):
编辑(2019 年 10 月):
6 年后,jQuery 文件上传显然仍然让人们发疯。如果您在此处的答案中发现一点安慰,请尝试search of NPM寻找 NPM寻找现代替代方案。这不值得麻烦,我保证。I recommended Uploadify in the previous edit but, as a commenter pointed out, they no longer appear to offer a free version. Uploadify was so2013 anyway.
我在之前的编辑中推荐了 Uploadify,但正如评论者指出的那样,他们似乎不再提供免费版本。Uploadify是那么2013呢。
EDIT:
编辑:
这似乎仍然获得了流量,所以我将解释我最终做了什么。我最终按照接受的答案中的教程使插件工作。然而,jQuery 文件上传是一个真正的麻烦,如果你正在寻找一个更简单的文件上传插件,我强烈推荐Uploadify上传。正如答案所指出的,它仅可免费用于非商业用途。Background
背景
I'm trying to use blueimp's jQuery File Uploadto allow users to upload files. Out of the box it works perfectly, following the setup instructions. But to use it practically on my website, I want to be able to do a couple of things:
我正在尝试使用 blueimp 的jQuery File Upload来允许用户上传文件。按照设置说明开箱即可完美运行。但是要在我的网站上实际使用它,我希望能够做几件事:
- Include the uploader on any of my existing pages
- Change the directory for uploaded files
- 在我现有的任何页面上包含上传器
- 更改上传文件的目录
All the files for the plugin are located in a folder under the root.
插件的所有文件都位于根目录下的文件夹中。
I've tried...
我试过了...
- Moving the demo page into the root and updating the paths for the necessary scripts
- Changing the 'upload_dir' and 'upload_url' options in the UploadHandler.php file as suggested here.
- Changing the URL in the second line of the demo javascript
- 将演示页面移动到根目录并更新必要脚本的路径
- 按照此处的建议更改 UploadHandler.php 文件中的“upload_dir”和“upload_url”选项。
- 更改演示 javascript 第二行中的 URL
In all cases, the preview shows, and the progress bar runs, but the files fail to upload, and I get this error in the console: Uncaught TypeError: Cannot read property 'files' of undefined
. I don't understand how all the parts of the plugin work which is making it difficult to debug.
在所有情况下,预览都会显示,并且进度条会运行,但文件无法上传,并且我在控制台中收到此错误:Uncaught TypeError: Cannot read property 'files' of undefined
。我不明白插件的所有部分是如何工作的,这使得调试变得困难。
Code
代码
The javascript in the demo page:
演示页面中的 javascript:
$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
var url = 'file_upload/server/php/UploadHandler.php',
uploadButton = $('<button/>')
.addClass('btn')
.prop('disabled', true)
.text('Processing...')
.on('click', function () {
var $this = $(this),
data = $this.data();
$this
.off('click')
.text('Abort')
.on('click', function () {
$this.remove();
data.abort();
});
data.submit().always(function () {
$this.remove();
});
});
$('#fileupload').fileupload({
url: url,
dataType: 'json',
autoUpload: false,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
maxFileSize: 5000000, // 5 MB
// Enable image resizing, except for Android and Opera,
// which actually support image resizing, but fail to
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
previewMaxWidth: 100,
previewMaxHeight: 100,
previewCrop: true
}).on('fileuploadadd', function (e, data) {
data.context = $('<div/>').appendTo('#files');
$.each(data.files, function (index, file) {
var node = $('<p/>')
.append($('<span/>').text(file.name));
if (!index) {
node
.append('<br>')
.append(uploadButton.clone(true).data(data));
}
node.appendTo(data.context);
});
}).on('fileuploadprocessalways', function (e, data) {
var index = data.index,
file = data.files[index],
node = $(data.context.children()[index]);
if (file.preview) {
node
.prepend('<br>')
.prepend(file.preview);
}
if (file.error) {
node
.append('<br>')
.append(file.error);
}
if (index + 1 === data.files.length) {
data.context.find('button')
.text('Upload')
.prop('disabled', !!data.files.error);
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .bar').css(
'width',
progress + '%'
);
}).on('fileuploaddone', function (e, data) {
$.each(data.result.files, function (index, file) {
var link = $('<a>')
.attr('target', '_blank')
.prop('href', file.url);
$(data.context.children()[index])
.wrap(link);
});
}).on('fileuploadfail', function (e, data) {
$.each(data.result.files, function (index, file) {
var error = $('<span/>').text(file.error);
$(data.context.children()[index])
.append('<br>')
.append(error);
});
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
});
我对缺乏文档感到惊讶;看起来改变应该是一件简单的事情。如果有人能解释如何做到这一点,我将不胜感激。
采纳答案by Subrat Pattnaik
I was looking for a similar functionality some days back and came across a good tutorial on tutorialzine. Here is an working example. Complete tutorial can be found here.
几天前我正在寻找类似的功能,并在tutorialzine上找到了一个很好的教程。这是一个工作示例。完整教程可以在这里找到。
Simple form to hold the file upload dialogue:
保存文件上传对话框的简单形式:
<form id="upload" method="post" action="upload.php" enctype="multipart/form-data">
<input type="file" name="uploadctl" multiple />
<ul id="fileList">
<!-- The file list will be shown here -->
</ul>
</form>
And here is the jQuery code to upload the files:
这是上传文件的jQuery代码:
$('#upload').fileupload({
// This function is called when a file is added to the queue
add: function (e, data) {
//This area will contain file list and progress information.
var tpl = $('<li class="working">'+
'<input type="text" value="0" data-width="48" data-height="48" data-fgColor="#0788a5" data-readOnly="1" data-bgColor="#3e4043" />'+
'<p></p><span></span></li>' );
// Append the file name and file size
tpl.find('p').text(data.files[0].name)
.append('<i>' + formatFileSize(data.files[0].size) + '</i>');
// Add the HTML to the UL element
data.context = tpl.appendTo(ul);
// Initialize the knob plugin. This part can be ignored, if you are showing progress in some other way.
tpl.find('input').knob();
// Listen for clicks on the cancel icon
tpl.find('span').click(function(){
if(tpl.hasClass('working')){
jqXHR.abort();
}
tpl.fadeOut(function(){
tpl.remove();
});
});
// Automatically upload the file once it is added to the queue
var jqXHR = data.submit();
},
progress: function(e, data){
// Calculate the completion percentage of the upload
var progress = parseInt(data.loaded / data.total * 100, 10);
// Update the hidden input field and trigger a change
// so that the jQuery knob plugin knows to update the dial
data.context.find('input').val(progress).change();
if(progress == 100){
data.context.removeClass('working');
}
}
});
//Helper function for calculation of progress
function formatFileSize(bytes) {
if (typeof bytes !== 'number') {
return '';
}
if (bytes >= 1000000000) {
return (bytes / 1000000000).toFixed(2) + ' GB';
}
if (bytes >= 1000000) {
return (bytes / 1000000).toFixed(2) + ' MB';
}
return (bytes / 1000).toFixed(2) + ' KB';
}
And here is the PHP code sample to process the data:
这是处理数据的 PHP 代码示例:
if($_POST) {
$allowed = array('jpg', 'jpeg');
if(isset($_FILES['uploadctl']) && $_FILES['uploadctl']['error'] == 0){
$extension = pathinfo($_FILES['uploadctl']['name'], PATHINFO_EXTENSION);
if(!in_array(strtolower($extension), $allowed)){
echo '{"status":"error"}';
exit;
}
if(move_uploaded_file($_FILES['uploadctl']['tmp_name'], "/yourpath/." . $extension)){
echo '{"status":"success"}';
exit;
}
echo '{"status":"error"}';
}
exit();
}
The above code can be added to any existing form. This program automatically uploads images, once they are added. This functionality can be changed and you can submit the image, while you are submitting your existing form.
上面的代码可以添加到任何现有的表单中。添加图像后,该程序会自动上传图像。此功能可以更改,您可以在提交现有表单的同时提交图像。
Updated my answer with actual code. All credits to original author of the code.
用实际代码更新了我的答案。全部归功于代码的原始作者。
Source: http://tutorialzine.com/2013/05/mini-ajax-file-upload-form/
来源:http: //tutorialzine.com/2013/05/mini-ajax-file-upload-form/
回答by Tim
I've just spent 2 hours battling with jQuery Upload but gave up because of the amount of dependencies (I had 13 JS files included to get all the bells and whistles).
我刚刚花了 2 个小时与 jQuery Upload 作斗争,但由于依赖项的数量而放弃了(我包含了 13 个 JS 文件来获得所有的花里胡哨)。
I did a bit more searching and came across a neat project called Dropzone.js, which does not have any dependencies.
我做了更多的搜索,发现了一个名为Dropzone.js的简洁项目,它没有任何依赖项。
The author has also created a bootstrap demowhich was inspired by the jQuery File Upload plugin.
作者还创建了一个受 jQuery 文件上传插件启发的引导程序演示。
I hope this saves someone else some time.
我希望这可以为其他人节省一些时间。
回答by Louis Ferreira
I also struggled with this but got it working once I figured out how the paths work in UploadHandler.php: upload_dir and upload_url are about the only settings to look at to get it working. Also check your server error logs for debugging information.
我也为此苦苦挣扎,但是一旦我弄清楚了 UploadHandler.php 中的路径如何工作,它就开始工作了:upload_dir 和 upload_url 是唯一需要查看的设置才能使其正常工作。还要检查您的服务器错误日志以获取调试信息。
回答by tvshajeer
Check out the Image drag and drop uploader with image preview using dropper jquery plugin.
使用 dropper jquery 插件查看带有图像预览的图像拖放上传器。
HTML
HTML
<div class="target" width="78" height="100"><img /></div>
JS
JS
$(".target").dropper({
action: "upload.php",
}).on("start.dropper", onStart);
function onStart(e, files){
console.log(files[0]);
image_preview(files[0].file).then(function(res){
$('.dropper-dropzone').empty();
//$('.dropper-dropzone').css("background-image",res.data);
$('#imgPreview').remove();
$('.dropper-dropzone').append('<img id="imgPreview"/><span style="display:none">Drag and drop files or click to select</span>');
var widthImg=$('.dropper-dropzone').attr('width');
$('#imgPreview').attr({width:widthImg});
$('#imgPreview').attr({src:res.data});
})
}
function image_preview(file){
var def = new $.Deferred();
var imgURL = '';
if (file.type.match('image.*')) {
//create object url support
var URL = window.URL || window.webkitURL;
if (URL !== undefined) {
imgURL = URL.createObjectURL(file);
URL.revokeObjectURL(file);
def.resolve({status: 200, message: 'OK', data:imgURL, error: {}});
}
//file reader support
else if(window.File && window.FileReader)
{
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = function () {
imgURL = reader.result;
def.resolve({status: 200, message: 'OK', data:imgURL, error: {}});
}
}
else {
def.reject({status: 1001, message: 'File uploader not supported', data:imgURL, error: {}});
}
}
else
def.reject({status: 1002, message: 'File type not supported', error: {}});
return def.promise();
}
$('.dropper-dropzone').mouseenter(function() {
$( '.dropper-dropzone>span' ).css("display", "block");
});
$('.dropper-dropzone').mouseleave(function() {
$( '.dropper-dropzone>span' ).css("display", "none");
});
CSS
CSS
.dropper-dropzone{
width:78px;
padding:3px;
height:100px;
position: relative;
}
.dropper-dropzone>img{
width:78px;
height:100px;
margin-top=0;
}
.dropper-dropzone>span {
position: absolute;
right: 10px;
top: 20px;
color:#ccc;
}
.dropper .dropper-dropzone{
padding:3px !important
}
回答by Sahip
This is good Angular plugin for uploading files, and its free!
这是用于上传文件的好 Angular 插件,而且是免费的!
回答by engineerDave
I struggled with this plugin for a while on Rails, and then someone gemified it obsoleting all the code I had created.
我在 Rails 上用这个插件挣扎了一段时间,然后有人把它宝石化,废弃了我创建的所有代码。
Although it looks like you're not using this in Rails, however if anyone is using it checkout this gem. The source is here --> jQueryFileUpload Rails.
虽然看起来你没有在 Rails 中使用它,但是如果有人使用它,请查看这个gem。来源在这里 --> jQueryFileUpload Rails。
Update:
更新:
In order to satisfy the commenter I've updated my answer. Essentially "use this gem, here is the source code" If it disappears then do it the long way.
回答by Iftikhar Khan
Hi try bellow link it is very easy. I've been stuck for long time and it solve my issue in few minutes. http://simpleupload.michaelcbrook.com/#examples
嗨,试试下面的链接,这很容易。我被困了很长时间,它在几分钟内解决了我的问题。 http://simpleupload.michaelcbrook.com/#examples
回答by Geremia
回答by CORSAIR
回答by Timothy Anyona
For the UI plugin, with jsp page and Spring MVC..
对于UI插件,用jsp页面和Spring MVC..
Sample html. Needs to be within a formelement with an idattribute of fileupload
示例html。需要在具有fileupload id属性的表单元素中
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="fileupload-buttonbar">
<div>
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files</span>
<input id="fileuploadInput" type="file" name="files[]" multiple>
</span>
<%-- https://stackoverflow.com/questions/925334/how-is-the-default-submit-button-on-an-html-form-determined --%>
<button type="button" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel upload</span>
</button>
<!-- The global file processing state -->
<span class="fileupload-process"></span>
</div>
<!-- The global progress state -->
<div class="fileupload-progress fade">
<!-- The global progress bar -->
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar progress-bar-success" style="width:0%;"></div>
</div>
<!-- The extended global progress state -->
<div class="progress-extended"> </div>
</div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/css/jquery.fileupload.css">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/css/jquery.fileupload-ui.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/vendor/jquery.ui.widget.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/jquery.iframe-transport.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/jquery.fileupload.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/jquery.fileupload-process.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/jquery.fileupload-validate.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/jquery.fileupload-ui.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var maxFileSizeBytes = ${maxFileSizeBytes};
if (maxFileSizeBytes < 0) {
//-1 or any negative value means no size limit
//set to undefined
//https://stackoverflow.com/questions/5795936/how-to-set-a-javascript-var-as-undefined
maxFileSizeBytes = void 0;
}
//https://github.com/blueimp/jQuery-File-Upload/wiki/Options
//https://stackoverflow.com/questions/34063348/jquery-file-upload-basic-plus-ui-and-i18n
//https://stackoverflow.com/questions/11337897/how-to-customize-upload-download-template-of-blueimp-jquery-file-upload
$('#fileupload').fileupload({
url: '${pageContext.request.contextPath}/app/uploadResources.do',
fileInput: $('#fileuploadInput'),
acceptFileTypes: /(\.|\/)(jrxml|png|jpe?g)$/i,
maxFileSize: maxFileSizeBytes,
messages: {
acceptFileTypes: '${fileTypeNotAllowedText}',
maxFileSize: '${fileTooLargeMBText}'
},
filesContainer: $('.files'),
uploadTemplateId: null,
downloadTemplateId: null,
uploadTemplate: function (o) {
var rows = $();
$.each(o.files, function (index, file) {
var row = $('<tr class="template-upload fade">' +
'<td><p class="name"></p>' +
'<strong class="error text-danger"></strong>' +
'</td>' +
'<td><p class="size"></p>' +
'<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">' +
'<div class="progress-bar progress-bar-success" style="width:0%;"></div></div>' +
'</td>' +
'<td>' +
(!index && !o.options.autoUpload ?
'<button class="btn btn-primary start" disabled>' +
'<i class="glyphicon glyphicon-upload"></i> ' +
'<span>${startText}</span>' +
'</button>' : '') +
(!index ? '<button class="btn btn-warning cancel">' +
'<i class="glyphicon glyphicon-ban-circle"></i> ' +
'<span>${cancelText}</span>' +
'</button>' : '') +
'</td>' +
'</tr>');
row.find('.name').text(file.name);
row.find('.size').text(o.formatFileSize(file.size));
if (file.error) {
row.find('.error').text(file.error);
}
rows = rows.add(row);
});
return rows;
},
downloadTemplate: function (o) {
var rows = $();
$.each(o.files, function (index, file) {
var row = $('<tr class="template-download fade">' +
'<td><p class="name"></p>' +
(file.error ? '<strong class="error text-danger"></strong>' : '') +
'</td>' +
'<td><span class="size"></span></td>' +
'<td>' +
(file.deleteUrl ? '<button class="btn btn-danger delete">' +
'<i class="glyphicon glyphicon-trash"></i> ' +
'<span>${deleteText}</span>' +
'</button>' : '') +
'<button class="btn btn-warning cancel">' +
'<i class="glyphicon glyphicon-ban-circle"></i> ' +
'<span>${clearText}</span>' +
'</button>' +
'</td>' +
'</tr>');
row.find('.name').text(file.name);
row.find('.size').text(o.formatFileSize(file.size));
if (file.error) {
row.find('.error').text(file.error);
}
if (file.deleteUrl) {
row.find('button.delete')
.attr('data-type', file.deleteType)
.attr('data-url', file.deleteUrl);
}
rows = rows.add(row);
});
return rows;
}
});
});
</script>
Sample upload and delete request handlers
示例上传和删除请求处理程序
@PostMapping("/app/uploadResources")
public @ResponseBody
Map<String, List<FileUploadResponse>> uploadResources(MultipartHttpServletRequest request,
Locale locale) {
//https://github.com/jdmr/fileUpload/blob/master/src/main/java/org/davidmendoza/fileUpload/web/ImageController.java
//https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#using-jquery-file-upload-ui-version-with-a-custom-server-side-upload-handler
Map<String, List<FileUploadResponse>> response = new HashMap<>();
List<FileUploadResponse> fileList = new ArrayList<>();
String deleteUrlBase = request.getContextPath() + "/app/deleteResources.do?filename=";
//http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/multipart/MultipartRequest.html
Iterator<String> itr = request.getFileNames();
while (itr.hasNext()) {
String htmlParamName = itr.next();
MultipartFile file = request.getFile(htmlParamName);
FileUploadResponse fileDetails = new FileUploadResponse();
String filename = file.getOriginalFilename();
fileDetails.setName(filename);
fileDetails.setSize(file.getSize());
try {
String message = saveFile(file);
if (message != null) {
String errorMessage = messageSource.getMessage(message, null, locale);
fileDetails.setError(errorMessage);
} else {
//save successful
String encodedFilename = URLEncoder.encode(filename, "UTF-8");
String deleteUrl = deleteUrlBase + encodedFilename;
fileDetails.setDeleteUrl(deleteUrl);
}
} catch (IOException ex) {
logger.error("Error", ex);
fileDetails.setError(ex.getMessage());
}
fileList.add(fileDetails);
}
response.put("files", fileList);
return response;
}
@PostMapping("/app/deleteResources")
public @ResponseBody
Map<String, List<Map<String, Boolean>>> deleteResources(@RequestParam("filename") List<String> filenames) {
Map<String, List<Map<String, Boolean>>> response = new HashMap<>();
List<Map<String, Boolean>> fileList = new ArrayList<>();
String templatesPath = Config.getTemplatesPath();
for (String filename : filenames) {
Map<String, Boolean> fileDetails = new HashMap<>();
String cleanFilename = ArtUtils.cleanFileName(filename);
String filePath = templatesPath + cleanFilename;
File file = new File(filePath);
boolean deleted = file.delete();
if (deleted) {
fileDetails.put(cleanFilename, true);
} else {
fileDetails.put(cleanFilename, false);
}
fileList.add(fileDetails);
}
response.put("files", fileList);
return response;
}
Sample class for generating the required json response
用于生成所需 json 响应的示例类
public class FileUploadResponse {
//https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#using-jquery-file-upload-ui-version-with-a-custom-server-side-upload-handler
private String name;
private long size;
private String error;
private String deleteType = "POST";
private String deleteUrl;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the size
*/
public long getSize() {
return size;
}
/**
* @param size the size to set
*/
public void setSize(long size) {
this.size = size;
}
/**
* @return the error
*/
public String getError() {
return error;
}
/**
* @param error the error to set
*/
public void setError(String error) {
this.error = error;
}
/**
* @return the deleteType
*/
public String getDeleteType() {
return deleteType;
}
/**
* @param deleteType the deleteType to set
*/
public void setDeleteType(String deleteType) {
this.deleteType = deleteType;
}
/**
* @return the deleteUrl
*/
public String getDeleteUrl() {
return deleteUrl;
}
/**
* @param deleteUrl the deleteUrl to set
*/
public void setDeleteUrl(String deleteUrl) {
this.deleteUrl = deleteUrl;
}
}
See https://pitipata.blogspot.co.ke/2017/01/using-jquery-file-upload-ui.html
见https://pitipata.blogspot.co.ke/2017/01/using-jquery-file-upload-ui.html