使用 wicket ajax post 将文件数组从 js 发送到 java
Sending file array from js to java using wicket ajax post
我正在使用文件类型的字段输入加载多个文件列表。问题是我想在表单发布之前从原始列表中删除其中一些。 Couse 文件列表在 js 中是不可变的,我无法创建新的输入来发布被覆盖的文件列表(js 安全原因( 我必须使用我要提交的文件构建数组。
但是我不知道如何使用 Wicket.Ajax.post 发布和接收它(由于上述我无法发布表单(
标准文件上传字段获取请求作为表单帖子上的IMultipartWebRequest的实例。如何使用 Wicket.Ajax.post 做同样的事情?
Wicket.Ajax.post(( 是 http://api.jquery.com/jquery.ajax/的包装器。它只是给你一些钩子,你可以在其中操作请求或响应:onBefore,onPrecondition,onSuccess等。因此,如果你找到一种方法来做你需要的普通jQuery,那么只需在onBeforeSend钩子中添加这个逻辑。
你已经可以使用MultiFileUpload来做到这一点了?您不需要自己构建它。
请参阅此检票口示例:http://www.wicket-library.com/wicket-examples/upload/multi
我遇到了同样的情况:当我一次/在一个文件输入字段中上传多个文件时,我想从文件列表中删除一个特定文件。Wicket 6.x 中提供的"MultiFileUploadField"会删除所有文件,如果它们一起被选中,这不是我想要的。因为我正在为现有软件制作一种插件,所以我无法将 Wicket 升级到较新版本,也无法在 Wicket 应用程序中挂载资源。
绝地先生在评论中提到:
据我所知,我使用了某种jQuery更新插件,并使用隐藏的输入做了一些技巧,以发送带有表单的文件。但我不确定,那是前段时间,我没有项目来源。
我的解决方案尚未完成,并且不使用上传插件(还?它可以用作使用 JavaScript 将文件上传到 Wicket 应用程序的"基础"。
关键组件是添加的 ajaxBehavior,它接收由 jQuery.ajax(( 提交的 FormData 对象。
需要注意的是,我使用 jQuery.ajax(( 将数据发布到 Wicket 应用程序,无需回退。
这可能不适用于较旧的浏览器。查看 jQuery 浏览器支持以获取更多信息。
另请注意,并非所有浏览器都完全支持 FormData 对象。
首先,我扩展了现有的MultiFileUploadField:
public class MyMultiFileUploadField extends MultiFileUploadField {
private static final long serialVersionUID = 1L;
private static final ResourceReference JS = new JavaScriptResourceReference(
MyMultiFileUploadField.class, "MyMultiFileUploadField.js");
private final WebComponent upload;
private final WebMarkupContainer container;
private final AbstractAjaxBehavior ajaxBehavior;
private final String componentIdPrefix;
private final int maxUploads;
private final boolean useMultipleAttr;
我们提供了自己的构造函数,在其中将 ajaxBehavior 添加到组件中:
public MyMultiFileUploadField(String id, IModel<? extends Collection<FileUpload>> model, int max,
boolean useMultipleAttr) {
super(id, model, max);
this.maxUploads = max;
this.useMultipleAttr = useMultipleAttr;
upload = (WebComponent) get("upload"); // Created by parent as: new WebComponent("upload");
container = (WebMarkupContainer) get("container"); // Created by parent as: new WebMarkupContainer("container");
ajaxBehavior = new MyMultiFileUploadBehavior();
add(ajaxBehavior);
}
还要重写 renderHead 方法,以便我们可以渲染我们自己的 JavaScript。
这里重要的是我们提供脚本的ajaxBehavior.getCallbackUrl()
。
@Override
public void renderHead(IHeaderResponse response) {
response.render(JavaScriptHeaderItem.forReference(JS));
response.render(OnDomReadyHeaderItem.forScript("new MultiFileUpload('" + getInputName() + "', document.getElementById('"
+ container.getMarkupId() + "'), " + maxUploads + ", " + useMultipleAttr + ", '" + ajaxBehavior.getCallbackUrl()
+ "').addElement(document.getElementById('" + upload.getMarkupId() + "'));"));
} // new MultiFileUpload(uploadFieldName, uploadContainer, maxUploads, useMultipleAttr, callbackUrl).addElement(fileInput);
ajaxBehavior 将接收文件并将它们传递给 FileHandler 类进行保存。
非常感谢David Tanzer在他的帖子jQuery Wicket中对此进行了解释。
import org.apache.wicket.behavior.AbstractAjaxBehavior;
import org.apache.wicket.markup.html.form.upload.FileUpload;
import org.apache.wicket.protocol.http.servlet.MultipartServletWebRequest;
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.handler.TextRequestHandler;
import org.apache.wicket.util.lang.Bytes;
import org.apache.wicket.util.upload.FileItem;
import org.apache.wicket.util.upload.FileUploadException;
public class MyMultiFileUploadBehavior extends AbstractAjaxBehavior {
private static final long serialVersionUID = 1L;
@Override
public void onRequest() {
final RequestCycle requestCycle = RequestCycle.get();
readRequest(requestCycle);
sendResponse(requestCycle);
}
private void readRequest(final RequestCycle requestCycle) {
Map<String, List<FileItem>> multiPartRequestFiles = null;
final ServletWebRequest webRequest = (ServletWebRequest) requestCycle.getRequest();
try {
MultipartServletWebRequest multiPartRequest = webRequest.newMultipartWebRequest(Bytes.megabytes(1), "UploadInfo");
multiPartRequest.parseFileParts();
multiPartRequestFiles = multiPartRequest.getFiles();
} catch (FileUploadException e) {
e.printStackTrace(System.out);
return;
}
if (multiPartRequestFiles != null && !multiPartRequestFiles.isEmpty()) {
for (Entry<String, List<FileItem>> entry : multiPartRequestFiles.entrySet()) {
// For debug: iterate over the map and print a list of filenames
final String name = entry.getKey();
System.out.println("Entry name: '" + name + "'");
final List<FileItem> fileItems = entry.getValue();
for (FileItem file : fileItems) {
System.out.println("Entry file: '" + file.getName() + "'");
}
List<FileUpload> fileUploads = buildFileUploadList(fileItems);
FileUploadForm.getUploadFileHandler().persistFiles(fileUploads);
}
}
}
private void sendResponse(final RequestCycle requestCycle) {
requestCycle.scheduleRequestHandlerAfterCurrent(
new TextRequestHandler("application/json", "UTF-8", "[]"));
}
private List<FileUpload> buildFileUploadList(List<FileItem> fileItems) {
List<FileUpload> fileUploads = new ArrayList<>(fileItems.size());
for (FileItem fileItem : fileItems) {
fileUploads.add(new FileUpload(fileItem));
}
return fileUploads;
}
}
您可以按照 Wicket 示例中所示的相同方式保留文件(RobAU 也提到过(。
至于JavaScript,我基于Stickman制作的Wicket 6.x附带的脚本。请注意,此脚本仍然非常基本。
有关将 wicket abstractajaxbehavior 与 jquery ajax 一起使用的更多详细信息。
有关使用 jquery ajax 发送多部分表单数据的更多信息。
/**
* @author Stickman -- http://the-stickman.com
* @author Vertongen
* @see /org/apache/wicket/markup/html/form/upload/MultiFileUploadField.js
*/
function MultiFileUpload(uploadFieldName, uploadContainer, maxUploads, useMultipleAttr, callbackUrl) {
"use strict";
console.log("Params: " + uploadFieldName+ ", " + uploadContainer + ", " + maxUploads + ", " + useMultipleAttr + ", " + callbackUrl);
// Is there a maximum?
if (!maxUploads) {
maxUploads = -1;
}
// Map to hold selected files. Key is formatted as: 'upload_' + uploadId
var formDataMap = new Map();
//this.formDataMap = formDataMap;
var uploadId = 0;
// Reference to the file input element
var fileInputElement = null;
/**
* Add a new file input element
*/
this.addElement = function(fileInput) {
// Make sure it's a file input element
if (fileInput.tagName.toLowerCase() === 'input' && fileInput.type.toLowerCase() === 'file') {
if (useMultipleAttr) {
fileInput.multiple = useMultipleAttr;
if (Wicket && Wicket.Browser.isOpera()) {
// in Opera 12.02, changing 'multiple' this way
// does not update the field
fileInput.type = 'button';
fileInput.type = 'file';
}
}
// Keep a reference to this MultiFileUpload object
fileInput.multiFileUpload = this;
// Keep a reference to the file input element
fileInputElement = fileInput;
// What to do when a file is selected
fileInput.onchange = function() {
// Check to see if we don't exceed the max.
if (maxUploads !== -1) {
if (this.files.length > maxUploads) {
console.warn("More files selected than allowed!");
this.value = "";
return;
}
if((this.files.length + formDataMap.size) > maxUploads) {
console.warn("Total amount of files for upload exceeds the maximum!");
this.value = "";
return;
}
}
// Put selected files in the FormDataMap
for (var i = 0, numFiles = this.files.length; i < numFiles; i++) {
uploadId++;
var fileId = "upload_" + uploadId;
var fileObj = this.files[i];
formDataMap.set(fileId, fileObj);
// Update uploadContainer add filenames to the list
this.multiFileUpload.addFileToUploadContainer(fileId, fileObj);
}
// Clear file input
this.value = "";
// If we've reached maximum number, disable file input element
if (maxUploads !== -1 && formDataMap.size >= maxUploads) {
this.disabled = true;
}
};
} else if (Wicket && Wicket.Log) {
Wicket.Log.error('Error: not a file input element');
}
};
this.addFileToUploadContainer = function(fileId, fileObj) {
// Row div
var new_row = document.createElement('tr');
var contentsColumn = document.createElement('td');
var buttonColumn = document.createElement('td');
// Delete button
var new_row_button = document.createElement('input');
new_row_button.id = fileId;
new_row_button.type = 'button';
new_row_button.value = 'Remove';
// Delete function
new_row_button.onclick = function() {
// Remove the selected file from the formData map.
formDataMap.delete(this.id);
// Remove this row from the list
this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);
// Re-enable file input element (if it's disabled)
fileInputElement.disabled = false;
// Appease Safari
// without it Safari wants to reload the browser window
// which nixes your already queued uploads
return false;
};
// Add filename and button to row
contentsColumn.innerHTML = this.getOnlyFileName(fileObj.name);
new_row.appendChild(contentsColumn);
new_row_button.style.marginLeft = '20px';
buttonColumn.appendChild(new_row_button);
new_row.appendChild(buttonColumn);
uploadContainer.appendChild(new_row);
};
var submitButton = document.getElementById('submitUploads');
var resetButton = document.getElementById('resetUploads');
var success = function() {console.log('success!'); };
var failure = function() {console.log('failure.'); };
var complete = function() {console.log('Done.'); };
submitButton.onclick = function() {
if(!formDataMap || formDataMap.size < 1) {
console.warn("No files selected, cancelled upload!");
return;
}
// Convert the Map into a FormData object.
var formData = new FormData();
formDataMap.forEach(function(value, key) {
console.log(key + ' = ' + value);
formData.append("uploads", value);
});
// Send the FormData object to our Wicket app.
jQuery.ajax({
url: callbackUrl,
type: 'POST',
data: formData,
context: self,
cache: false,
processData: false,
contentType: false,
success: [success],
error: [failure],
// complete: [complete]
});
};
resetButton.onclick = function() {
formDataMap.clear();
fileInputElement.disabled = false;
};
this.getOnlyFileName = function(file) {
var toEscape = {
"&" : "&",
"<" : "<",
">" : ">",
'"' : '"',
"'" : '''
};
function replaceChar(ch) {
return toEscape[ch] || ch;
}
function htmlEscape(fileName) {
return fileName.replace(/[&<>'"]/g, replaceChar);
}
var separatorIndex1 = file.lastIndexOf('''');
var separatorIndex2 = file.lastIndexOf('/');
separatorIndex1 = Math.max(separatorIndex1, separatorIndex2);
var fileName = separatorIndex1 >= 0 ? file.slice(separatorIndex1 + 1, file.length) : file;
fileName = htmlEscape(fileName);
return fileName;
};
}
您可能还希望为多文件上传字段添加 HTML 副本。
<wicket:panel xmlns:wicket="http://wicket.apache.org">
<input wicket:id="upload" type="file" class="wicket-mfu-field" />
<div wicket:id="container" class="wicket-mfu-container">
<div wicket:id="caption" class="wicket-mfu-caption"></div>
</div>
</wicket:panel>
要使用MyMultiFileUploadField
类,您可以查看 Wicket 示例(RobAU 也提到了(。下面的代码和 HTML 基于 Wicket 示例。
// collection that will hold uploaded FileUpload objects
private final Collection<FileUpload> uploads = new ArrayList<>();
public FileUploadForm(String formId, MultiUploadConfig multiUploadConfig) {
super(formId);
// set this form to multipart mode (always needed for uploads!)
setMultiPart(true);
// Add one multi-file upload field with this class attribute "uploads" as model
multiFileUploadField = new MyMultiFileUploadField("fileInput",
new PropertyModel<Collection<FileUpload>>(this, "uploads"),
multiUploadConfig.getMaxNumberOfFiles(), true);
add(multiFileUploadField);
// Set the maximum size for uploads
setMaxSize(Bytes.megabytes(multiUploadConfig.getMaxUploadSize()));
// Set maximum size of each file in upload request
setFileMaxSize(Bytes.megabytes(multiUploadConfig.getMaxFileSize()));
}
public static IUploadFileHandler getUploadFileHandler() {
return _uploadFileHandler;
}
public static void setUploadFileHandler(IUploadFileHandler uploadFileHandler) {
_uploadFileHandler = uploadFileHandler;
}
我在具有以下HTML的Wicket形式中使用MyMultiFileUploadField
。
<fieldset>
<legend>Upload form</legend>
<p>
<div wicket:id="fileInput" class="mfuex" />
</p>
<input wicket:id="submitUploads" type="submit" value="Upload"/>
</fieldset>
- 如何从Java/scala调用js美化程序
- 使用js或extjs访问对象的java列表
- 如何在不同的java程序中捕获JS可变值
- Node JS,传统的数据结构?(如Set等),任何类似Java.util的node
- 如何通过子进程连接Java应用程序后在node.js中编写文件
- 翻译是从哪里来的?Java servlet、tomcat和Ext Js Sencha应用程序
- Java,nashorn访问另一个js文件
- 如何将 js 中的 var 转换为 java
- 使用 Selenium 和 java 测试 React JS 下拉列表
- 为什么这个js代码的RSA加密结果与java的RSA标准代码不同
- Node.js套接字读取()类似Java
- html5/JS中的java桌面应用程序gui
- 如何在Java中使用Google Caja HTML/CSS消毒JS库
- 解析从js发送到Java的json字符串时出错
- 使用deployJava.js时,禁用重定向到移动设备上的java.com
- 如何使File.js(java脚本文件)在特定页面中执行和加载,而不在其他页面中加载
- Google Maps API v3最近是否发生了与mootools.js Java Script不兼容的更改,导致控件
- JSP - JS - Java interaction
- 使用sugar .js Java-Script获取当前月份
- 使用javascript Jasmine单元测试,Web项目(html + css + js + java/spring