이 개찰구 예제를 참조하십시오 내가 하나 개의 파일 입력 필드에/한 번에 여러 파일을 업로드 할 때 파일 목록에서 특정 파일을 삭제하고 싶었다. Wicket 6.x에서 제공되는 'MultiFileUploadField'는 모든 파일을 함께 선택했으면 삭제합니다. 이는 원하지 않는 것입니다. 기존 소프트웨어에 일종의 플러그인을 만들고 있기 때문에 Wicket을 최신 버전으로 업그레이드 할 수 없으며 Wicket 애플리케이션에 리소스를 마운트 할 수 없습니다.
내 솔루션이 아직 완료되지 않았으며 업로드 플러그인을 사용하지 않았습니다 (아직?). JavaScript를 사용하여 Wicket 응용 프로그램에 파일을 업로드하는 수단으로 '기본'으로 사용할 수 있습니다.
임계 성분 jQuery.ajax()에 의해 제출 된 개체 FormData 를 수신 첨가 ajaxBehavior이다.
주의 사항 나는 대체 데이터없이 Wicket 응용 프로그램에 POST 데이터에 jQuery.ajax()을 사용합니다.
이전 브라우저에서는 작동하지 않을 수 있습니다. 자세한 내용은 jQuery browser support을 확인하십시오.
아직 모든 브라우저에서 FormData objects을 완전히 지원하지는 않습니다.
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 메소드를 오버라이드 (override) :
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를 추가 할 우리 자신의 생성자를 제공
먼저 나는 기존 MultiFileUploadField 확장 .
여기서 중요한 것은 스크립트에 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 클래스에 전달합니다.
그의 게시물 jQuery Wicket에서 이것을 설명 해주신 David Tanzer에게 감사드립니다.
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;
}
}
(또한 RobAU 언급)을 Wicket Examples에서와 같이 파일 같은 방식을 지속 할 수 있습니다.
JavaScript는 Stickman이 만든 Wicket 6.x와 함께 제공되는 스크립트를 기반으로합니다. 이 스크립트는 여전히 매우 기본적인 기능입니다.
자세한 내용은 using wicket abstractajaxbehavior with jquery ajax.
sending multipart formdata with 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;
};
}
JavaScript가 아직 완전하게 테스트되지 않았습니다. 내가 문제를 발견하면 스크립트의 업데이트를 게시 할 것입니다.
또한 MultiFileUploadField에 대한 HTML 사본을 추가 할 수도 있습니다. (또한 RobAU 언급)는 Wicket Examples에서 볼 수 있습니다 MyMultiFileUploadField
클래스를 사용하기 위해
<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>
. 아래의 코드와 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>
안녕하세요 Mr Jedi 님, 여기에 설명 된 문제를 해결할 수 있었습니까? 나는 같은 상황에 있습니다 : 한 번에 여러 파일을 업로드하면 파일 목록에서 특정 파일을 삭제하고 싶습니다/한 파일 입력 필드에 있습니다. Wicket 6.x에서 제공되는 'MultiFileUploadField'는 모든 파일을 함께 선택했으면 삭제합니다. 이는 원하지 않는 것입니다. 기존 소프트웨어에 일종의 플러그인을 만들고 있기 때문에 Wicket을 최신 버전으로 업그레이드 할 수 없으며 Wicket 응용 프로그램에 리소스를 마운트 할 수 없습니다. – Vertongen
@Vertongen 필자는 jQuery uploder plugin을 사용하여 숨겨진 입력 내용을 사용하여 이러한 파일을 양식과 함께 전송했다는 것을 기억한다. 그러나 나는 확신 할 수 없다. 그것은 얼마 전이었고 나는 프로젝트 소스를 가지고 있지 않다. –
빠른 답장을 보내 주셔서 감사합니다. 나쁜 소식은 더 이상 소스가 없습니다. 내가 그것을 발견했을 때 나는 그것을 지키고 대답을 게시 할 것이다. – Vertongen