在Wicket中上传多文件的FileNotFoundException

时间:2013-05-03 20:27:57

标签: java ajax file-upload wicket

我们正在使用Wicket 6+并且在FileUpload.writeTo(文件)上有一个奇怪的错误。 它只发生在某些类型的文件(docx,xl​​sx,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)

2 个答案:

答案 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>