>美观且易于管理(但可选)
>上传时快速且永不失败
>包括进度条
>显示预览
>多文件上传支持
>上传文件大小和类型限制
>拖放
>客户端图像可调整大小(这是我的主要功能,因为我上传的所有文件都是图像)
有一个插件MultiFileUpload.是的,它非常适合我的大多数要求,但不适用于客户端大小的图像大小调整.所以我决定使用JQuery FileUpload,因为它支持Client side Image Resizing.
我用vaadin Window上传图片.但是我在创建窗口时遇到了问题,分别很难创建每个HTML元素(可能我的exp少了).所以我使用CustomLayout with HTML轻松创建和编辑我的图像上传窗口的设计.
下面是我的自定义布局HTML文件. (两个脚本是图像预览模板)
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0,file; file=o.files[i]; i++) { %}
<tr class="template-upload">
<td width="100px" align="center">
<span class="preview"></span>
</td>
<td width="400px" align="center">
<p class="name">{%=file.name%}</p>
{% if (!o.files.error) { %}
<div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valueNow="0"><div class="bar" style="width:0%;"></div></div>
{% } %}
{% if (file.error) { %}
<div><span class="label label-important">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td width="100px" align="center">
{% if (!i) { %}
<button style="display: none;" class="start" type="button">
<span>Start</span>
</button>
<div class="v-button v-widget cancel" type = "button">
<span class="v-button-wrap" style="color: red;">
<span class="v-button-caption">Cancel</span>
</span>
</div>
{% } %}
<br>
{%=o.formatFileSize(file.size)%}
</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0,file; file=o.files[i]; i++) { %}
<tr class="template-download">
<td width="100px" align="center">
<span class="preview">
{% if (file.path) { %}
<img src="../{%=file.path%}" width="100px">
{% } %}
</span>
</td>
<td width="400px" align="center">
<p class="name">
{%=file.name%}
</p>
{% if (file.error) { %}
<div><span class="label label-important">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td width="100px" align="center">
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
</tr>
{% } %}
</script>
<table cellpadding="5" style="width: 100%;">
<colgroup>
<col>
</colgroup>
<tbody>
<tr>
<td width="90px">
<div style="text-align: right; width: 120px;">UploadPhoto :</div>
</td>
<td>
<div id="pnlProgress" aria-valueNow="0" aria-valuemax="100" aria-valuemin="0" style="display: none;" class="progress progressall progress-success progress-striped active">
<div style="width: 0%;" class="allbar" id="pnlProgressBar"> </div>
</div>
</td>
</tr>
<tr>
<td colspan="3">
<div id="imageForm" style="width: 600px;">
<form id="fileupload">
<div style="margin-bottom: 10px; border: 1px solid #DDD; width: 600px; height: 300px; overflow: scroll">
<table cellspacing="0" cellpadding="5">
<tbody class="files"></tbody>
</table>
</div>
<div style="margin-bottom: 10px;" class="fileupload-buttonbar">
<div class="v-button v-widget btnPlus">
<span class="v-button-caption">Add Files</span>
<input type="file" multiple="" name="files[]">
</div>
<div class="v-button v-widget start" type = "submit">
<span class="v-button-wrap">
<span class="v-button-caption">StartUpload</span>
</span>
</div>
<div class="v-button v-widget cancel" type = "reset">
<span class="v-button-wrap">
<span class="v-button-caption">Cancel All</span>
</span>
</div>
</div>
<div style="border: 1px solid #999; width: 600px; height: 100px;" id="dropZone">
<div class="carPhotoDropMsg">
Draft & Drop Photos<br>(jpg,jpeg,png,gif only)
</div>
</div>
</form>
</div>
</td>
</tr>
</tbody>
下面是ImageUpload窗口
public final class ImageUploadDialog extends CustomComponent {
private Window window;
public void show() {
UI.getCurrent().addWindow(window);
// 123 is seq for save in database or other use
Page.getCurrent().getJavaScript().execute("initimageuploader(123)");
}
public ImageUploadDialog() {
CustomLayout layout = new CustomLayout("imageUploadLayout");
window = new Window("Uploading Photos");
window.center();
window.setWidth("615px");
window.setModal(true);
window.setResizable(false);
window.setClosable(true);
window.setContent(layout);
}
}
以下是我的upload.js文件,用于初始化我的图像上传器
function initimageuploader(seq) {
$('#fileupload').fileupload({
url : 'photo/upload.html?s=' + seq,sequentialUploads : true,disableImageResize : false,imageMaxWidth : 1024,imageMaxHeight : 1024,previewCrop : true,dropZone : $("#dropZone"),acceptFileTypes : /(\.|\/)(gif|jpe?g|png)$/i,progress : function(e,data) {
if (data.context) {
var progress = data.loaded / data.total * 100;
progress = Math.floor(progress);
$('.progress').attr('aria-valueNow',progress);
$('.progress').css('display','block');
$('.bar').css('width',progress + '%');
}
},progressall : function(e,data) {
var progress = data.loaded / data.total * 100;
progress = Math.floor(progress);
$('.progressall').attr('aria-valueNow',progress);
$('.progressall').css('display','block');
$('.allbar').css('width',progress + '%');
if (progress > 20) {
$('.allbar').text(progress + '% Completed');
}
},stop: function (e) {
return;
}
});
}
你需要额外的javascripts文件用于图像上传器,我在我的UI类中导入它们,如下所示
@JavaScript({ "vaadin://themes/myproject/js/load-image.min.js","vaadin://themes/myproject/js/tmpl.min.js","vaadin://themes/myproject/js/jquery/jquery-1.10.1.min.js","vaadin://themes/myproject/js/jquery/vendor/jquery.ui.widget.js","vaadin://themes/myproject/js/jquery/jquery.iframe-transport.js","vaadin://themes/myproject/js/jquery/jquery.fileupload.js","vaadin://themes/myproject/js/jquery/jquery.fileupload-ui.js","vaadin://themes/myproject/js/jquery/jquery.fileupload-process.js","vaadin://themes/myproject/js/jquery/jquery.fileupload-image.js","vaadin://themes/myproject/js/jquery/jquery.fileupload-validate.js","vaadin://themes/myproject/js/canvas-to-blob.min.js","vaadin://themes/myproject/js/upload.js" })
@StyleSheet({ "vaadin://themes/myproject/css/jquery-ui-1.10.3.custom.min.css","vaadin://themes/myproject/css/imageUpload.css" })
public class EntryPoint extends UI {
..............
}
Please Notice for JS Files Order !
下面是我的图像上传窗口的自定义CSS文件(imageUpload.css)
table.upld-status {
display: none;
}
.fileupload-buttonbar .btnPlus {
float: left;
position: relative;
overflow: hidden;
color: blue;
text-align: center;
margin-right : 10px;
}
.fileupload-buttonbar .btnPlus input {
margin: 0px;
position: absolute;
top: 0px;
right: 0px;
line-height: 30px;
font-size: 23px;
direction: ltr;
opacity: 0;
}
.carPhotoDropMsg {
color: #DDD;
font-size: 20pt;
height: 82%;
padding: 9px;
text-align: center;
}
.progress {
background-color: #F7F7F7;
background-image: linear-gradient(to bottom,#F5F5F5,#F9F9F9);
background-repeat: repeat-x;
border-radius: 4px 4px 4px 4px;
Box-shadow: 0 1px 2px rgba(0,0.1) inset;
height: 17px;
overflow: hidden;
}
.progress-success.progress-striped .bar,.progress-success.progress-striped .allbar,.progress
striped .bar-success {
background-color: #62C462;
background-image: linear-gradient(45deg,rgba(255,255,0.15) 25%,transparent 25%,transparent 50%,0.15) 50%,0.15) 75%,transparent 75%,transparent);
}
.progress.active .bar,.progress.active .allbar {
animation: 2s linear 0s normal none infinite progress-bar-stripes;
}
.progress-success .bar,.progress-success .allbar,.progress .bar-success {
background-color: #5EB95E;
background-image: linear-gradient(to bottom,#62C462,#57A957);
background-repeat: repeat-x;
}
.progress-striped .bar,.progress-striped .allbar {
background-color: #149BDF;
background-image: linear-gradient(45deg,transparent);
background-size: 40px 40px;
}
.progress .bar,.progress .allbar {
-moz-Box-sizing: border-Box;
background-color: #0E90D2;
background-image: linear-gradient(to bottom,#149BDF,#0480BE);
background-repeat: repeat-x;
Box-shadow: 0 -1px 0 rgba(0,0.15) inset;
color: #FFFFFF;
float: left;
font-size: 12px;
height: 100%;
text-align: center;
text-shadow: 0 -1px 0 rgba(0,0.25);
transition: width 0.4s ease 0s;
width: 0;
}
我需要服务器端控制来保存图像.你需要两个罐子apache-common-io和apache-common-fileupload.下面是这两个罐子的maven存储库.
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
最后,下面是服务器端控制的代码.
@WebServlet(value = "/photo/upload.html")
public class UploadServletController extends HttpServlet {
protected final void doPost(final HttpServletRequest request,final HttpServletResponse response) throws servletexception,IOException {
response.setContentType("application/json");
PrintWriter out = response.getWriter();
FileItemFactory factory = new diskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> fields = null;
try {
fields = upload.parseRequest(request);
}
catch (FileUploadException e) {
throw new RuntimeException("Error Parsing File Item " + e.getMessage(),e);
}
if (fields != null) {
String message = uploadPhoto(request,fields);
out.write(message);
}
}
public final synchronized String uploadPhoto(final HttpServletRequest request,final List<FileItem> sessionFiles) {
List<Map<String,Object>> ret = new ArrayList<Map<String,Object>>();
for (FileItem item : sessionFiles) {
if (!item.isFormField()) {
Long seq = Long.parseLong(request.getParameter("s"));
// get from vm arguments (eg:-DstaticDir=/Applications/springsource/workspace/myproject/src/main/webapp)
String staticDir = System.getProperty("staticDir");
Date today = new Date();
SimpleDateFormat fmtYMD = new SimpleDateFormat("/yyyyMMdd/HH");
SimpleDateFormat fmtHMS = new SimpleDateFormat("HHmmssS");
String saveDir = "data/photo" + fmtYMD.format(today);
String format = ".jpg";
try {
format = item.getName().substring(item.getName().lastIndexOf("."),item.getName().length())
.toLowerCase();
}
catch (Exception e) {
// nothing to do!
}
String fileName = seq + "_" + fmtHMS.format(today) + format;
Map<String,Object> res = new HashMap<String,Object>();
// Save image in specify location
String filePath = staticDir + "/" + saveDir;
saveFile(filePath,fileName,item);
res.put("seq",seq);
res.put("path",saveDir + "/" + fileName);
res.put("ext",format.substring(1));
res.put("name",item.getName());
res.put("size",item.getSize());
ret.add(res);
}
}
Map<String,Object> result = new HashMap<String,Object>();
result.put("files",ret);
JSONObject obj = new JSONObject(result);
return obj.toString();
}
public static String saveFile(final String filePath,final String fileName,final FileItem item) {
File file = new File(filePath);
if (!file.exists()) {
file.mkdirs();
}
File imageFile = new File(file,fileName);
try {
item.write(imageFile);
}
catch (Exception e) {
e.printstacktrace();
}
item.setFieldName(filePath + fileName);
return item.toString();
}
}
我知道我的代码可能有风险和一些弱点.欢迎提出任何建议.但我相信新手有一些用处(我也是新手).抱歉格式太长,不好.
最后一件事是我的问题….
为什么预览图像(上传后不上传之前)自动包含url而不是filepath?我找不到图像错误
"NetworkError: 404 Not Found - http://localhost:8080/myproject/VAADIN/themes/myTheme/data/photo/20140723/23/123_235918346.jpg"
实际上这个图像路径应该是data / photo / 20140723/23 / 111_235918346.jpg.我不知道为什么前缀url http:// localhost:8080 / myproject / VAADIN / themes / myTheme /是自动包含的(可能是由于我的CustomLayout HTML文件路径)?文件路径来自HTTP响应(使用JSON).我认为这是由于VAADIN,因为它适用于我的GWT项目,或者可能是我错了.有什么建议么 ?感谢您阅读我的问题.
解决方法
<script id="template-download" type="text/x-tmpl">
{% for (var i=0,file; file=o.files[i]; i++) {; %}
<tr class="template-download">
<td width="100px" align="center">
<span class="preview">
{% if (file.path) { %}
<img src="/myproject/{%=file.path%}" width="100px">
{% } %}
</span>
</td>
<td width="400px" align="center">
<p class="name">
{%=file.name%}
</p>
{% if (file.error) { %}
<div><span class="label label-important">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td width="100px" align="center">
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
</tr>
{% } %}
</script>
现在每个人都很好.如果您没有立即看到图像,请检查您的IDE(Eclipse或STS)设置如下
Preference > General > Workspace
并选中复选框访问时刷新和使用本机挂钩或轮询刷新.