标签:用户 selector 安装 false write 列表 9.png 就是 throws
一、认识FineUploader的功能:进入示例网站:https://fineuploader.com/demos.html#basic-setup;
二、准备相关的js,css
git clone https://github.com/FineUploader/fine-uploader.git
cd fine-uploader
npm install
make build
make build之后将生成一个“_build”目录,其中包含CSS、JS、图像和模板文件,以供所有可能构建的Fine Uploader。

上面是下载的fine-Uploader前台所需的代码。下面来看看后台代码:
三:服务器示例代码:
git clone https://github.com/FineUploader/server-examples/blob/master/java/UploadReceiver.java

我们所需要的java代码就在java那个目录下:

到现在,准备工作已经完成。
四、新建一个自己的web项目:

1、输入工程名,finish之后目录结构是这样的:

2、添加刚才在server-example中的java文件到src下:
然后这样直接会报错,应该在java文件中修改所在包名,并引入所有需要的jar包:

目前暂时引入了这些包。
3、接下来新建html了:
从刚才在git上下载的fine-Uploader文件夹中的client/html/templates中找到这次示例要用的html文件:gallery.html
(https://docs.fineuploader.com/features/styling.html 这里会涉及这几个文件的讲解)

<script type="text/template" id="qq-template"> <div class="qq-uploader-selector qq-uploader qq-gallery" qq-drop-area-text="Drop files here"> <div class="qq-total-progress-bar-container-selector qq-total-progress-bar-container"> <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-total-progress-bar-selector qq-progress-bar qq-total-progress-bar"></div> </div> <div class="qq-upload-drop-area-selector qq-upload-drop-area" qq-hide-dropzone> <span class="qq-upload-drop-area-text-selector"></span> </div> <div class="qq-upload-button-selector qq-upload-button"> <div>Upload a file</div> </div> <span class="qq-drop-processing-selector qq-drop-processing"> <span>Processing dropped files...</span> <span class="qq-drop-processing-spinner-selector qq-drop-processing-spinner"></span> </span> <ul class="qq-upload-list-selector qq-upload-list" role="region" aria-live="polite" aria-relevant="additions removals"> <li> <span role="status" class="qq-upload-status-text-selector qq-upload-status-text"></span> <div class="qq-progress-bar-container-selector qq-progress-bar-container"> <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" class="qq-progress-bar-selector qq-progress-bar"></div> </div> <span class="qq-upload-spinner-selector qq-upload-spinner"></span> <div class="qq-thumbnail-wrapper"> <img class="qq-thumbnail-selector" qq-max-size="120" qq-server-scale> </div> <button type="button" class="qq-upload-cancel-selector qq-upload-cancel">X</button> <button type="button" class="qq-upload-retry-selector qq-upload-retry"> <span class="qq-btn qq-retry-icon" aria-label="Retry"></span> Retry </button> <div class="qq-file-info"> <div class="qq-file-name"> <span class="qq-upload-file-selector qq-upload-file"></span> <span class="qq-edit-filename-icon-selector qq-btn qq-edit-filename-icon" aria-label="Edit filename"></span> </div> <input class="qq-edit-filename-selector qq-edit-filename" tabindex="0" type="text"> <span class="qq-upload-size-selector qq-upload-size"></span> <button type="button" class="qq-btn qq-upload-delete-selector qq-upload-delete"> <span class="qq-btn qq-delete-icon" aria-label="Delete"></span> </button> <button type="button" class="qq-btn qq-upload-pause-selector qq-upload-pause"> <span class="qq-btn qq-pause-icon" aria-label="Pause"></span> </button> <button type="button" class="qq-btn qq-upload-continue-selector qq-upload-continue"> <span class="qq-btn qq-continue-icon" aria-label="Continue"></span> </button> </div> </li> </ul> <dialog class="qq-alert-dialog-selector"> <div class="qq-dialog-message-selector"></div> <div class="qq-dialog-buttons"> <button type="button" class="qq-cancel-button-selector">Close</button> </div> </dialog> <dialog class="qq-confirm-dialog-selector"> <div class="qq-dialog-message-selector"></div> <div class="qq-dialog-buttons"> <button type="button" class="qq-cancel-button-selector">No</button> <button type="button" class="qq-ok-button-selector">Yes</button> </div> </dialog> <dialog class="qq-prompt-dialog-selector"> <div class="qq-dialog-message-selector"></div> <input type="text"> <div class="qq-dialog-buttons"> <button type="button" class="qq-cancel-button-selector">Cancel</button> <button type="button" class="qq-ok-button-selector">Ok</button> </div> </dialog> </div> </script>
将上面的代码全部复制到新建的html文件:
然后在代码中引入fineUploader的核心js和css:
gallery.html必须使用fine-uploader-gallery.css文件,
以上是假如有图片上传的显示模板,那么得需要一个供图片拖动到的位置:(如示例网站):
此时此刻,我们需要对定义的该位置,“绑定”fine-Uploader组件:
<script type="text/javascript">
function createUploader() {
uploader = new qq.FineUploader({
element: document.getElementById('fine-uploader-gallery'),
autoUpload: true, //是否自动上传,true就会自动上传
multiple : true, //multiple选项:默认为true,用户可以一次选择多个文件并上传。
request: { //后台接受文件上传的URL路径。设置其中的endpoint属性。
endpoint: '/FineUploaderServerExample/servlet/UploadReceiver'
},
/**
session: {
endpoint: '<%=request.getContextPath()%>/XXXX/XXXX',
params: {'id': ${bulletin.id}}
},
*/
deleteFile: { //用于删除已上传的文件。可以删除的文件必须是在同一个页面中已经成功上传,或者由session选项初始化的文件列表。
enabled: true,
endpoint: '/FineUploaderServerExample/servlet/UploadReceiver', //后台用于删除文件的URL地址。返回值和上传时一样必须含有“success”属性
method: 'POST',//必须设置为'post'
forceConfirm: true, //是否出现删除确认的对话框,默认值为false
confirmMessage: '确定要删除文件 {filename} 吗? 不可恢复!!',
params: {
foo: "bar"
},
deletingFailedText: '删除失败!'
},
text : {
uploadButton : "<a href='#' class='add_files'><span class='icon-attachment'></span>浏览</a>"
},
validation:
{
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png'],
itemLimit:12,
sizeLimit: 2048 // 200 kB = 200 * 1024 bytes
},
editFilename: {
enabled: false
},
onSubmit: function(id, fileName) {
},
onUpload: function(id, fileName) {
},
//loaded:表示已经上传到服务器端数据的大小[byte].
//total: 需要上传文件的大小.
onProgress: function(id, fileName, loaded, total) {
},
onComplete: function(id, fileName, responseJSON) {
},
//id表示第几个开始上传的文件,Fine Uploder定义是默认从0开始计数.
//fileName:上传文件的文件名.
onCancel: function(id, fileName) {
},
callbacks: {
onAllComplete: function(successIDs, failIDs) {
if(submitFile)
submitdata(successIDs);
}
},
params:{
param1:"value1",
param2:"value2"
},
retry: {
enableAuto: true
},
debug:true
});
}
window.onload = createUploader;
</script>endpoint: '/FineUploaderServerExample/servlet/UploadReceiver',
endpoint这里:FineUploaderServerExample是工程名,/servlet/UploaderReceiver是访处理post请求的servlet的类。
至此,test.html就基本完成了。(然后加上web.xml)
4、修改刚才复制到项目中的server-example中的Java代码:
通过代码结构可以看出,UploadReceiver.java是直接处理上传和删除请求的类:
由于前台endpoint中请求的后台url都是post请求的,所以我们首先来看看doPost方法:
大致来看,第一步,根据请求的HttpRequest,临时存放文件的文件夹,上下文传入MultipartUploadParser这个类。
根据MultipartUploadParser类的构造方法,返回一个MultipartUploadParser实体。那我们看看在构造方法里是执行了什么操作:
public MultipartUploadParser(HttpServletRequest request, File repository, ServletContext context) throws Exception
{
//创建临时文件夹
if (!repository.exists() && !repository.mkdirs())
{
throw new IOException("Unable to mkdirs to " + repository.getAbsolutePath());
}
//servlet实现文件上传---核心API—DiskFileItemFactory
fileItemsFactory = setupFileItemFactory(repository, context);
//在setupFileItemFactory中指定临时文件目录,并给该目录设置了一个文件清理跟踪器
//临时文件在不再被使用的时候(如果相应的java.io.File是可回收的则更好)会自动被删除.(文件清理跟踪器)
ServletFileUpload upload = new ServletFileUpload(fileItemsFactory);
List<FileItem> formFileItems = upload.parseRequest(request);
//将request进行解析并添加到FileItem中
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())
{
System.out.println("log.isDebugEnabled");
writeDebugInfo(request);
}
}
}获得一个 MultipartUploadParser之后,再据此获得一个RequestParser类的实例。
static RequestParser getInstance(HttpServletRequest request, MultipartUploadParser multipartUploadParser) throws Exception
{
RequestParser requestParser = new RequestParser();
if (multipartUploadParser == null)
{
if (request.getMethod().equals("POST") && request.getContentType() == null)
{
parseXdrPostParams(request, requestParser);
}
else
{
requestParser.filename = request.getParameter(FILENAME_PARAM);
parseQueryStringParams(requestParser, request);
}
}
else
{
requestParser.uploadItem = multipartUploadParser.getFirstFile();
requestParser.filename = multipartUploadParser.getFirstFile().getName();
//params could be in body or query string, depending on Fine Uploader request option properties
parseRequestBodyParams(requestParser, multipartUploadParser);
parseQueryStringParams(requestParser, request);
}
removeQqParams(requestParser.customParams);
return requestParser;
}RequestParser的作用就是将前台传过来的文件信息获取,并填充自己的属性:

获得RequestParser之后,用writeFileForMultipartRequest方法写到指定位置:
private void writeFileForMultipartRequest(RequestParser requestParser) throws Exception {
File dir = new File(UPLOAD_DIR, requestParser.getUuid());//在指定的文件夹下,创建一个子文件夹,名为对应的uuid
dir.mkdirs();
System.out.println("writeFileForMultipartRequest === ");
if (requestParser.getPartIndex() >= 0) {
writeFile(requestParser.getUploadItem().getInputStream(),
new File(dir, requestParser.getUuid() + "_" + String.format("%05d", requestParser.getPartIndex())),
null);
if (requestParser.getTotalParts() - 1 == requestParser.getPartIndex()) {
File[] parts = getPartitionFiles(dir, requestParser.getUuid());
File outputFile = new File(dir, requestParser.getOriginalFilename());//timg.jpg
for (File part : parts) {
mergeFiles(outputFile, part);
}
assertCombinedFileIsVaid(requestParser.getTotalFileSize(), outputFile, requestParser.getUuid());
deletePartitionFiles(dir, requestParser.getUuid());
}
} else {
writeFile(requestParser.getUploadItem().getInputStream(), new File(dir, requestParser.getFilename()), null);
}
// option.add(++id, requestParser.getFilename(), requestParser.getUuid(), requestParser.getUuid().substring(5, 8));
}//需要注意的是,这个文件夹如果没有指定绝对路径,那么遇到过的情况是:1、在桌面,2、在eclipse的安装目录。
我这写的是绝对路径。
写入的文件会这样存放:

每个文件的上层文件夹的名字就是其对应的uuid。
5、运行项目,添加缺少的文件,比如前台需要的gif图:

将报错的这几个文件都加入到css文件夹中。这样还可以完成删除操作。

这样就完成了fineuploader的例子使用。
标签:用户 selector 安装 false write 列表 9.png 就是 throws
原文地址:http://blog.51cto.com/12176710/2061604