welcome to xlongwei.com

欢迎大家一起学习、交流、分享


QQ:9167702333 邮箱:admin@xlongwei.com

uploadify图片上传功能


分类 JavaScript   关键字 分享   标签 java   ourjs   web   发布 hongwei  1425886408504
注意 转载须保留原文链接,译文链接,作者译者等信息。  
uploadify是一款基于flash的jQuery上传插件,flash提供了浏览器兼容性支持,图片上传是很通用的基础性功能,本文简要介绍uploadify的配置使用、UploadController的服务端实现、以及如何扩展OurJS使图片上传更方便。
<script type="text/javascript" src="/upload/jquery-1.11.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="/upload/uploadify-3.2.1/uploadify.css" />
<script type="text/javascript" src="/upload/uploadify-3.2.1/jquery.uploadify.min.js"></script>
<script type="text/javascript">
var settings = {
swf : "$static_url/uploadify-3.2.1/uploadify.swf",
cancelImg : "$static_url/uploadify-3.2.1/uploadify-cancel.png",
buttonText : "选择文件...",
uploader : "$upload/upload/temp",
formData : {type : "image" },
fileObjName : "file",
fileTypeExts : "*.png;*.jpg;*.jpeg",
fileTypeDesc : "图片文件",
fileSizeLimit : 2048,
successTimeout : 90
};
function uploadify(fileInputId, pathInputId){
$(fileInputId).uploadify(jQuery.extend(settings, {
onUploadSuccess:function(file, data, response){
var paths = data.split(",");//返回domain,path,domain+path就是图片访问地址,path存入数据库
$(pathInputId).val(paths[1]).next("a").attr("href",paths[0]+paths[1]).text("预览");
}
}));
}
$(function() {
uploadify("#file_upload1", "#path1");
});
</script>
<input name="path1" id="path1" class="Mtext1-1"/><a href="" target="_blank" style="display:none"></a>
<input type="file" name="file1" id="file_upload1" />
uploadify会渲染上传按钮#file_upload1

图片上传后会将path写入#path1,然后显示预览链接。

下面是UploadController处理文件上传请求
@RequestMapping("direct")
public Object direct(@RequestParam(defaultValue="image") String type, @RequestParam(defaultValue="false") boolean rename, MultipartFile file) {
String path = rename ? path(type, file.getOriginalFilename()) : type+"/"+file.getOriginalFilename();
File target = new File(GlobalConfig.getProperty(uploads_file), path);
boolean save = save(target, file);
if(save) {
logger.info("upload "+file.getOriginalFilename()+" ("+target.length()/1024+"K) to: " + path);
return string(GlobalConfig.getProperty(uploads)+","+path);
}
return null;
}
/**
* 临时上传文件至/uploads/temp
*/
@RequestMapping("temp")
public Object temp(@RequestParam(defaultValue="image") String type, MultipartFile file) {
String path = path(type, file.getOriginalFilename());
File target = new File(GlobalConfig.getProperty(uploads_temp_file), path);
boolean save = save(target, file);
if(save) {
logger.info("temp upload "+file.getOriginalFilename()+" ("+target.length()/1024+"K) to: " + path);
return string(GlobalConfig.getProperty(uploads_temp)+","+path);
}
return null;
}
/**
* 确认文件后从/uploads/temp移动至/uploads
*/
@RequestMapping("confirm")
public Object confirm(String path) {
boolean move = move(GlobalConfig.getProperty(uploads_temp_file), GlobalConfig.getProperty(uploads_file), path);
return move ? "1" : "0";
}
/** UMEditor上传图片支持,代码同imageUp.jsp */
@RequestMapping("umeditor")
public void umeditor(HttpServletRequest request, HttpServletResponse response) throws Exception {
Uploader up = new Uploader(request);
up.setSaveDir(GlobalConfig.getProperty("uploads_file"));
up.setSavePath("umeditor");
String[] fileType = {".gif" , ".png" , ".jpg" , ".jpeg" , ".bmp"};
up.setAllowFiles(fileType);
up.setMaxSize(10000); //单位KB
up.upload();

String callback = request.getParameter("callback");

String result = "{\"name\":\""+ up.getFileName() +"\", \"originalName\": \""+ up.getOriginalName() +"\", \"size\": "+ up.getSize() +", \"state\": \""+ up.getState() +"\", \"type\": \""+ up.getType() +"\", \"url\": \""+ up.getUrl() +"\"}";

result = result.replaceAll( "\\\\", "\\\\" );

if( callback == null ){
logger.info(result);
response.getWriter().print( result );
}else{
String print = "<script>"+ callback +"(" + result + ")</script>";
logger.info(print);
response.getWriter().print(print);
}
}
保守的做法是/upload/temp+/upload/confirm,先上传到temp目录(方便定期清理),提交表单时再confirm到正式目录。/upload/direct则是直接上传至正式目录(rename=true时重命名文件)。/upload/umeditor配置百度编辑器UMeditor上传图片(Uploader已由UM提供源码)。
public static String direct(String type, MultipartFile file) {
return uploadImpl(type, file, GlobalConfig.getProperty(upload_direct));
}
public static String direct(String type, File file) {
MultipartFile multipartFile = adapted(file);
if(multipartFile!=null) return direct(type, multipartFile);
else return null;
}
public static boolean confirm(String path) {
return pathImpl(path, GlobalConfig.getProperty(upload_confirm));
}
private static String uploadImpl(String type, MultipartFile file, String uri) {
if(file==null || file.isEmpty()) return null;
try {
HttpEntity entity = MultipartEntityBuilder.create()
.setMode(HttpMultipartMode.RFC6532)
.addTextBody("type", type, textUtf8)
.addBinaryBody("file", file.getInputStream(), ContentType.DEFAULT_BINARY, file.getOriginalFilename())
.build();
HttpUriRequest request = RequestBuilder.post()
.setUri(adapted(uri))
.setEntity(entity)
.build();
HttpResponse response = httpClient.execute(request);
String string = EntityUtils.toString(response.getEntity());
logger.info("upload "+file.getOriginalFilename()+" ("+file.getSize()/1024+"K) to: " + uri);
logger.info(string);
return string;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static boolean pathImpl(String path, String uri) {
if(path == null || path.length() == 0) return false;
HttpEntity entity = MultipartEntityBuilder.create()
.setMode(HttpMultipartMode.RFC6532)
.addTextBody("path", path, textUtf8)
.build();
HttpUriRequest request = RequestBuilder.post()
.setUri(adapted(uri))
.setEntity(entity)
.build();
try {
HttpResponse response = httpClient.execute(request);
String string = EntityUtils.toString(response.getEntity());
boolean result = "1".equals(string);
logger.info(uri+"?path="+path+" result: "+result);
return result;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
private static String adapted(String uri) {
return uri + ".html";
}
private static MultipartFile adapted(File file) {
try {
return new AdaptedMultipartFile(file, "file");
}catch (Exception e) {
return null;
}
}
public static class AdaptedMultipartFile implements MultipartFile {
private File file;
private String name;
byte[] content;
public AdaptedMultipartFile(File file, String name) throws IOException {
this.file = file;
this.name = name;
content = FileCopyUtils.copyToByteArray(file);
}
public String getName() {
return name;
}
public String getOriginalFilename() {
return file.getName();
}
public String getContentType() {
return null;
}
public boolean isEmpty() {
return content.length == 0;
}
public long getSize() {
return content.length;
}
public byte[] getBytes() throws IOException {
return content;
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(this.content);
}
public void transferTo(File dest) throws IOException, IllegalStateException {
FileCopyUtils.copy(this.content, dest);
}
}
表单提交时需要/upload/confirm确认图片有效,可以调用UploadUtil.confirm(path),UploadUtil还支持将表单提交的MultipartFile或者本地文件File上传到服务器。
OurJS编辑文章时引入图片是使用URL,以下是简单扩展(修改文件ourjs/web/newspaper/root/edit.tmpl):
<link rel="stylesheet" href="http://cms.xlongwei.com/res/js/uploadify-3.2.1/uploadify.css" />
<script src="http://cms.xlongwei.com/res/js/uploadify-3.2.1/jquery.uploadify.min.js"></script>
<script>
var static_url = "http://www.xlongwei.com/res";
var upload = "http://www.xlongwei.com";//nginx使用proxy_pass将上传请求代理给tomcat的UploadController
var settings = {
swf : static_url+"/js/uploadify-3.2.1/uploadify.swf",
cancelImg : static_url+"/js/uploadify-3.2.1/uploadify-cancel.png",
buttonText : "选择文件...",
uploader : upload+"/upload/direct.html",
formData : {type : "img/"+new Date().getFullYear(), rename : true }, //图片按年分目录
fileObjName : "file",
fileTypeExts : "*.png;*.jpg;*.jpeg",
fileTypeDesc : "图片文件",
fileSizeLimit : 2048,
successTimeout : 90
};
function uploadify(fileInputId, pathInputId){
$(fileInputId).uploadify(jQuery.extend(settings, {
onUploadSuccess:function(file, data, response){
var paths = data.split(",");
var imgUrl = upload+"/uploads/"+paths[1];//引用图片时需要完整URL
$(pathInputId).val(imgUrl).next("a").attr("href",imgUrl).text("预览");
}
}));
}
$(function() {
uploadify("#file_upload1", "#path1");
});
</script>
<div>
<label for="path1">上传图片</label>
<input name="path1" id="path1" style="width:1100px" size="90"/><a href="" target="_blank" style="padding:10px"></a>
<input type="file" name="file1" id="file_upload1" />
</div>
uploadify的跨域问题是个麻烦……,参考uploadify文件上传跨域问题