FineUploader使用心得

本文介绍了FineUploader的使用,包括所需代码、Java后台处理、参数解析和删除文件功能。FineUploader是一个纯JavaScript实现的文件上传组件,支持Ajax上传且不刷新页面。文章提供了关键配置选项的解释,并给出了后台处理文件上传和删除的Java代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

近来做一个需要有附件管理的公告版,于是发现了这个FineUploader,纯Javascript实现,Ajax方式,上传文件不刷新页面,不依赖于任何第三方库,非常好用。但刚开始使用时google了很多资料,包括官方的文档和demo。发现网上的很多资料要么很老,要么对我参考意义不大。至这个功能完成,写下自己的心得,给自己留点记录,如果能对别人有点参考价值则更佳。

FineUploader官方网站:http://fineuploader.com/ ,打包好的js是要收费的,价格还不便宜。

开源的项目:https://github.com/FineUploader/fine-uploader

本文中用到的FineUploader已上传到http://download.youkuaiyun.com/detail/jxiaoliu/8071341(已精简,去掉了所有用不到的文件,包括模板)

一、FineUploader所需的代码

首先,引入必须的js文件和css

<link href="<%=request.getContextPath()%>/fineuploader5/fineuploader-5.0.2.css" rel="stylesheet"/>
<script src="<%=request.getContextPath()%>/fineuploader5/fineuploader-5.0.2.js" type="text/javascript"></script>
OK,就这两个文件就可以了。

接下来,就可以在js中实例化这个uploader:

var submitFile = false;//用于控制仅在”提交“按钮按下时提交文件
var uploader = null;
function createUploader() {
	uploader = new qq.FineUploader({
		element: document.getElementById('fine-uploader'),
		autoUpload: false,
	      	request: {
	        	endpoint: '<%=request.getContextPath()%>/updownfile/UploadFile?op=add'
	      	},
	      	session: {
	      		endpoint: '<%=request.getContextPath()%>/manage/Bulletin?op=getattach',
	      		params: {'id': ${bulletin.id}}
	      	},
	      	deleteFile: {
	      		enabled: true,
	      		endpoint: '<%=request.getContextPath()%>/manage/Bulletin?op=del',
	      		method: 'POST',
	      		forceConfirm: true,
	      		confirmMessage: '确定要删除文件 {filename} 吗? 不可恢复!!',
	      		deletingFailedText: '删除失败!'
	      	},
	      	editFilename: {
	      	       enabled: false
	      	},
	      	callbacks: {
	      		onAllComplete:  function(successIDs, failIDs)  {
	      			if(submitFile)
	      				submitdata(successIDs);
	      		}
	      	}
	});
}
必须在页面初始化时进行此操作,继续加入下面这句:

window.onload = createUploader;
FineUploader必须实例化到html页面中的某个“容器”内,一般为<div>元素,第一个选项“element”即指出对应的html元素。所以在页面中必须有如下元素存在:

<div id="fine-uploader"></div>
此外,由于FineUploader分为core和UI两个类别,其中core应该是用户完全定制到自己的JS程序中去的,需要写自己的用户界面。对于初学者或一般用户来说,可以直接使用FineUploader提供的模板(template,用户可以去开源项目中下载),这里是直接拷贝模板文件(default.html)中相应的代码段到当前html页面的任意位置:

<script type="text/template" id="qq-template">
  <div class="qq-uploader-selector qq-uploader">
    <div class="qq-upload-button-selector qq-upload-button">
      <div>上传附件</div>
    </div>
    <ul class="qq-upload-list-selector qq-upload-list">
      <li>
        <div class="qq-progress-bar-container-selector">
          <div class="qq-progress-bar-selector qq-progress-bar"></div>
        </div>
        <span class="qq-upload-spinner-selector qq-upload-spinner"></span>
        <span class="qq-edit-filename-icon-selector qq-edit-filename-icon"></span>
        <span class="qq-upload-file-selector qq-upload-file"></span>
        <span class="qq-upload-size-selector qq-upload-size"></span>
        <a class="qq-upload-cancel-selector qq-upload-cancel" href="#">放弃上传</a>
        <a class="qq-upload-retry-selector qq-upload-retry" href="#">Retry</a>
        <a class="qq-upload-delete-selector qq-upload-delete" href="#">删除</a>
        <span class="qq-upload-status-text-selector qq-upload-status-text"></span>
      </li>
    </ul>
  </div>
</script>
很多文档或资料说最外层的<script>标记可以不要,但本人测试不可以,必须要。其中的id属性 id=" qq-template"至关重要,否则FineUploader不知道何处去查找自己的UI界面并展示。

该模板的样式可以通过fineuploader-5.0.2.css文件进行所需的修改,这里不再赘述。

至此,FineUploader已完整,当然要运行必须要后台代码的上传支持。

二、后台Java代码

借助于apache.commons.fileupload组件进行文件的上传,代码如下:

try {
	MultipartUploadParser UploadParser = new MultipartUploadParser(request, new File(System.getProperty("java.io.tmpdir")));
	FileItem uploadfile = UploadParser.getFirstFile();
	Path file = java.nio.file.Paths.get(uploadfile.getName());
	uploadfile.write(new File(rootpath + "/temp/" + file.getFileName().toString()));
	result.put("success", true);
} catch (Exception e) {
	result.put("success", false);
	response.getWriter().print(result.toString());
	e.printStackTrace();
}

必须注意的是,文件上传成功后,必须返回前台一个JSON格式的对象,其中必须含有一个"success"对象,其值为true或者false,代表着文件上传的成功或失败。

另外,当用户选择多个文件并上传时,是以多线程的方式各自独立同时进行的。每一个文件上传成功都会触发callbacks中的onComplete事件,所有文件上传成功后触发onAllComplete事件。

其中的MultipartUploadParser类对象定义如下:

package updownfile;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;

public class MultipartUploadParser
{
	final Logger log = LoggerFactory.getLogger(MultipartUploadParser.class);

	private Map
  
    params = new HashMap
   
    ();

	private List
    
      files = new ArrayList
     
      ();

	// fileItemsFactory is a field (even though it's scoped to the constructor) to prevent the
	// org.apache.commons.fileupload.servlet.FileCleanerCleanup thread from attempting to delete the
	// temp file before while it is still being used.
	//
	// FileCleanerCleanup uses a java.lang.ref.ReferenceQueue to delete the temp file when the FileItemsFactory marker object is GCed
	private DiskFileItemFactory fileItemsFactory;

	@SuppressWarnings("unchecked")
	public MultipartUploadParser(HttpServletRequest request, File repository) throws Exception
	{
		if (!repository.exists() && !repository.mkdirs())
		{
			throw new IOException("Unable to mkdirs to " + repository.getAbsolutePath());
		}

		fileItemsFactory = setupFileItemFactory(repository);

        ServletFileUpload upload = new ServletFileUpload(fileItemsFactory);
        List
      
        formFileItems = upload.parseRequest(request);

		parseFormFields(formFileItems);

		if (files.isEmpty())
		{
			log.warn("No files were found when processing the requst. Debugging info follows.");

			writeDebugInfo(request);

			throw new FileUploadException("No files were found when processing the requst.");
		}
		else
		{
			if (log.isDebugEnabled())
			{
				writeDebugInfo(request);
			}
		}
	}

	private DiskFileItemFactory setupFileItemFactory(File repository)
	{
		DiskFileItemFactory factory = new DiskFileItemFactory();
		factory.setSizeThreshold(10*1024*1024);
		factory.setRepository(repository);

	//	FileCleaningTracker pTracker = FileCleanerCleanup.getFileCleaningTracker(context);
	//	factory.setFileCleaningTracker(pTracker);

		return factory;
	}

	private void writeDebugInfo(HttpServletRequest request)
	{
		log.debug("-- POST HEADERS --");
		for (String header : Collections.list(request.getHeaderNames()))
		{
			log.debug("{}: {}", header, request.getHeader(header));
		}

		log.debug("-- POST PARAMS --");
		for (String key : params.keySet())
		{
			log.debug("{}: {}", key, params.get(key));
		}
	}

	private void parseFormFields(List
       
         items) throws UnsupportedEncodingException { for (FileItem item : items) { if (item.isFormField()) { String key = item.getFieldName(); String value = item.getString("UTF-8"); if (StringUtils.isNotBlank(key)) { params.put(key, StringUtils.defaultString(value)); } } else { files.add(item); } } } public Map
        
          getParams() { return params; } public List
         
           getFiles() { if (files.isEmpty()) { throw new RuntimeException("No FileItems exist."); } return files; } public FileItem getFirstFile() { if (files.isEmpty()) { throw new RuntimeException("No FileItems exist."); } return files.iterator().next(); } } 
         
        
       
      
     
    
   
  

三、代码中各选项含义

下面稍微详细的介绍组件用到的几个选项,方便各位根据自己项目的需要进行更改。
  • autoUpload选项:控制用户选择文件后是否立即自动上传选中的文件,默认为true,即选中后自动上传到服务器,上传完毕后,会依次显示文件名、文件大小及一个“删除”链接(删除上传文件的解释见deleteFile选项)。这里设置值为false,表示用户选择文件后仅列出文件(此时文件名右侧会出现“放弃”链接,点此链接会去除对应的文件),在需要时手动通过uploadStoredFiles()方法进行上传。
  • multiple选项:默认为true,用户可以一次选择多个文件并上传。
  • request选项:后台接受文件上传的URL路径。设置其中的endpoint属性。
  • editFilename选项:设置是否可修改上传的文件名(本人测试时好像没发现有什么作用~~)
  • callbacks选项:回调函数,可以监听各种事件。具体的可参见官方文档。
  • deleteFile选项:用于删除已上传的文件。可以删除的文件必须是在同一个页面中已经成功上传,或者由session选项初始化的文件列表。其重要的子选项解释如下:
         endpoint:后台用于删除文件的URL地址。返回值和上传时一样必须含有“success”属性
         method:重要,必须设置为'post'
         forceConfirm:是否出现删除确认的对话框,默认值为false
  • session选项:该选项确定控件初始化时需要初始化的文件列表。若不设置该项,则初始化控件时其文件列表为空。若需要给出用户以前已经上传的文件列表,则必须设置其子选项endpoint的值以从后台返回文件列表。后台返回的值必须是一个JSON格式的数组,每个数组的对象是JSON格式的对象,必须包含“name”和“uuid”两个属性,以分别指定文件名和文件的唯一代号。具体可参看官方文档。
需要注意的是,如果之前定义了onAllComplete事件,则初始化文件列表时,每一个文件都会触发onAllComplete事件,这是因为初始化好的每个文件状态都是qq.status.UPLOAD_SUCCESSFUL,即标志为已上传成功。所以本文开头定义了一个submitFile变量并设置其初始值为false,用于判断是用户手动提交上传文件还是页面初始化,如无此判断,onAllComplete事件中的代码会重复执行。

四、几张简单的样图

1. 文件已选择,待上传:


2. 文件上传过程:

3. 文件上传成功:

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值