我们正在使用Wicket 6+并且在FileUpload.writeTo(文件)上有一个奇怪的错误。 它只发生在某些类型的文件(docx,xlsx,java)上,并且只在一种形式下发生。完全相同的代码可以在其他地方附加文件。有帮助吗?谢谢。
HTML:
<div wicket:id="filesInput"/>
爪哇:
add(new org.apache.wicket.markup.html.form.upload.MultiFileUploadField("filesInput",
new PropertyModel<Collection<FileUpload>>(this, "uploads"), 5));
行fileUpload.writeTo(文件)上抛出错误;当从表单onSubmit调用时。
private void writeToFile(FileUpload fileUpload, Attachment attachment) {
if (fileUpload == null) {
return;
}
File file = AttachmentUtils.getFile(attachment, jtracHome);
try {
fileUpload.writeTo(file);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
错误日志:
2013-05-03 12:57:23,731 [http-bio-8084-exec-9] ERROR [org.apache.wicket.DefaultExceptionMapper] - Unexpected error occurred
org.apache.wicket.WicketRuntimeException: Method onFormSubmitted of interface org.apache.wicket.markup.html.form.IFormSubmitListener targeted at [SpaceItemViewForm [Component id = form]] on component [SpaceItemViewForm [Component id = form]] threw an exception
at org.apache.wicket.RequestListenerInterface.internalInvoke(RequestListenerInterface.java:268)
at org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:216)
at org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.invokeListener(ListenerInterfaceRequestHandler.java:240)
at org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.respond(ListenerInterfaceRequestHandler.java:226)
at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:840)
at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:254)
at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:211)
at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:282)
at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:244)
at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:188)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:267)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:75)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.apache.wicket.RequestListenerInterface.internalInvoke(RequestListenerInterface.java:258)
... 31 more
Caused by: java.lang.RuntimeException: java.io.FileNotFoundException: C:\Users\aeb\AppData\Roaming\NetBeans\7.2.1\apache-tomcat-7.0.27.0_base\temp\upload_9108b655_6177_4450_8e82_a767f101dd40_1997755963.tmp (The system cannot find the file specified)
at info.jtrac.JtracImpl.writeToFile(JtracImpl.java:405)
at info.jtrac.JtracImpl.storeScopeOfWork(JtracImpl.java:2053)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:301)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:198)
at $Proxy11.storeScopeOfWork(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:301)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy12.storeScopeOfWork(Unknown Source)
at info.jtrac.wicket.SpaceItemViewFormPanel$SpaceItemViewForm.onSubmit(SpaceItemViewFormPanel.java:433)
at org.apache.wicket.markup.html.form.Form$9.component(Form.java:1246)
at org.apache.wicket.markup.html.form.Form$9.component(Form.java:1240)
at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:274)
at org.apache.wicket.util.visit.Visits.visitPostOrder(Visits.java:245)
at org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1239)
at org.apache.wicket.markup.html.form.Form.process(Form.java:921)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:767)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:700)
... 36 more
Caused by: java.io.FileNotFoundException: C:\Users\aib\AppData\Roaming\NetBeans\7.2.1\apache-tomcat-7.0.27.0_base\temp\upload_9108b655_6177_4450_8e82_a767f101dd40_1997755963.tmp (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at org.apache.wicket.util.upload.DiskFileItem.write(DiskFileItem.java:439)
at org.apache.wicket.markup.html.form.upload.FileUpload.writeTo(FileUpload.java:234)
at info.jtrac.JtracImpl.writeToFile(JtracImpl.java:402)
答案 0 :(得分:1)
所以这是异常来自的代码:
if (!outputFile.renameTo(file))
{
BufferedInputStream in = null;
BufferedOutputStream out = null;
try
{
in = new BufferedInputStream(new FileInputStream(outputFile));
out = new BufferedOutputStream(new FileOutputStream(file));
Streams.copy(in, out);
}
finally
{
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
}
javadoc:
这种方法只能保证一次,第一次调用它时 特别的项目。这是因为,如果该方法重命名临时文件,那么 文件将不再可用于以后再次复制或重命名。
异常来自“outputFile”文件的打开 - 就好像它不再存在一样。是否有可能renameTo成功对文件执行某些操作,但renameTo方法仍然返回false?你能在那里设置一个断点,看看发生了什么吗?也许你不知何故叫它两次?
来自renameTo的javadoc:
此方法行为的许多方面都是固有的 依赖于平台:重命名操作可能无法移动 从一个文件系统到另一个文件系统的文件,它可能不是原子的,它 如果文件具有目标抽象路径名,则可能不会成功 已经存在。应始终检查返回值以确保 重命名操作成功。
答案 1 :(得分:0)
我刚刚运行了wicket MultiUploadPage example,一切正常。 向我们提供有关您的网页结构的更多详细信息,您的网页有何不同之处?
WicketApplication.java
public class WicketApplication extends WebApplication {
private Folder uploadFolder = null;
@Override
public Class<? extends WebPage> getHomePage(){
return HomePage.class;
}
public Folder getUploadFolder(){
return uploadFolder;
}
@Override
public void init(){
super.init();
getResourceSettings().setThrowExceptionOnMissingResource(false);
uploadFolder = new Folder(System.getProperty("java.io.tmpdir"), "wicket-uploads");
uploadFolder.mkdirs();
getApplicationSettings().setUploadProgressUpdatesEnabled(true);
}
}
HomePage.java
public class HomePage extends WebPage {
private static final long serialVersionUID = 1L;
private final FileListView fileListView;
public HomePage(final PageParameters parameters){
Folder uploadFolder = getUploadFolder();
final FeedbackPanel uploadFeedback = new FeedbackPanel("uploadFeedback");
add(uploadFeedback);
final FileUploadForm simpleUploadForm = new FileUploadForm("simpleUpload");
add(simpleUploadForm);
add(new Label("dir", uploadFolder.getAbsolutePath()));
fileListView = new FileListView("fileList", new LoadableDetachableModel<List<File>>(){
private static final long serialVersionUID = 1L;
@Override
protected List<File> load(){
return Arrays.asList(getUploadFolder().listFiles());
}
});
add(fileListView);
}
private class FileListView extends ListView<File>{
private static final long serialVersionUID = 1L;
public FileListView(String name, final IModel<List<File>> files){
super(name, files);
}
@Override
protected void populateItem(ListItem<File> listItem){
final File file = listItem.getModelObject();
listItem.add(new Label("file", file.getName()));
listItem.add(new Link<Void>("delete"){
private static final long serialVersionUID = 1L;
@Override
public void onClick(){
Files.remove(file);
info("Deleted " + file);
}
});
}
}
private class FileUploadForm extends Form<Void>{
private static final long serialVersionUID = 1L;
private final Collection<FileUpload> uploads = new ArrayList<FileUpload>();
public FileUploadForm(String name){
super(name);
setMultiPart(true);
add(new MultiFileUploadField("fileInput", new PropertyModel<Collection<FileUpload>>(this, "uploads"), 5, true));
setMaxSize(Bytes.kilobytes(100000));
}
@Override
protected void onSubmit(){
for (FileUpload upload : uploads){
File newFile = new File(getUploadFolder(), upload.getClientFileName());
try{
newFile.createNewFile();
upload.writeTo(newFile);
HomePage.this.info("saved file: " + upload.getClientFileName());
} catch (Exception e){
throw new IllegalStateException("Unable to write file");
}
}
}
}
private Folder getUploadFolder(){
return ((WicketApplication) Application.get()).getUploadFolder();
}
}
HomePage.html
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta charset="utf-8" />
<title>Apache Wicket Quickstart</title>
<link rel="stylesheet" href="style.css" type="text/css" media="screen" title="Stylesheet" />
</head>
<body>
The multi upload field is based on javascript found
<a target="_blank" href="http://the-stickman.com/web-development/javascript/upload-multiple-files-with-a-single-file-element/">here</a>.
<br />
<br /> Wicket can also handle file uploads via AJAX, please see AJAX
examples section. AJAX Functionality is not included in this example to
keep things simple.
<br />
<br />
<form wicket:id="simpleUpload">
<fieldset>
<legend>Upload form</legend>
<p>
<div wicket:id="fileInput" class="mfuex" />
</p>
<input type="submit" value="Upload!" />
</fieldset>
</form>
<div><span wicket:id="uploadFeedback" /></div>
<div>
<h4>Current files in <span wicket:id="dir">(dir)</span>:</h4>
<table>
<tr wicket:id="fileList">
<td width="200"><span wicket:id="file">(file)</span></td>
<td><a href="#" wicket:id="delete"><img src="delete.gif" border="0" /></a></td>
</tr>
</table>
</div>
</body>
</html>