覆盖 java.io.FileOutputStream 方法 [英] Override java.io.FileOutputStream method

查看:55
本文介绍了覆盖 java.io.FileOutputStream 方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定这是否是问这个问题的正确方式,但我会尝试解释我的情况以及我需要什么.

I'm not sure if that's the right way to ask this, but I'm gonna try to explain my case and what I need.

我有一个很大的 java 项目,它在许多不同的 java 类中上传文件,比如太多,我有大约 7 个不同的主文件夹来上传文件.目前的文件保存在 webapp 上下文中,我需要将它们保存在上下文之外.

I have a big java project, that upload files in many different java classes, like too many, and I have around 7 different main folders where the files are uploaded. The files at the moment are saved inside the webapp context, and I need to save them outside of context.

如果只有几个类上传这些文件,我可以花几天时间更改每个类并将其定向到上下文之外的路径,但是类太多了,所以我必须想办法在不更改每个类或根本不更改任何类的情况下执行此操作,这将是理想的.

If there were only a few classes that upload these files I could spend a few days changing every class and direct it to a path outisde of context, but there are way too many classes, so I have to figure out a way to do it without changing every class, or any class at all, which would be ideal.

每次上传都是通过以下方式完成的:

Every upload is done in the following way:

我得到了我的主要文件夹之一的真实路径:

I get real path of one of my main folders:

String realpath = httpServletRequest.getSession()
                                    .getServletContext()
                                    .getRealPath("/mainfolder1/mainsubfolder1/");

然后我获取文件并设置自定义文件名:

Then I get the file and set custom file name:

FormFile file = myForm.getFile();
String contentType = file.getContentType();
String fileName  = file.getFileName();
int fileSize     = file.getFileSize();
customFileName = "anyName" + fileName.substring(fileName.lastIndexOf("."));

然后我验证并保存文件:

Then I validate and save the file:

if (fileSize > 0 && contentType != null && fileName.length() > 0){
    InputStream in = file.getInputStream();
    OutputStream bos = new FileOutputStream(realpath + "/" + customFileName);

    int byteRead = 0;
    byte[] buffer = new byte[8192];
    while ((byteRead = in.read(buffer, 0, 8192)) != -1){
      bos.write(buffer, 0, byteRead);
    }
    bos.close();
    in.close();
}

保存我的文件的非常简单的方法,如您所见,它们保存在上下文中.

Very simple way to save my files, and as you can see, they are saved inside context.

因此,如果我能以某种方式覆盖 java.io.FileOutputStream,不仅将其保存在上下文中,而且还可以在上下文之外进行复制,那就太好了,例如将其保存在指定路径中以及其他路径中上下文之外的路径.

So if I could somehow override java.io.FileOutputStream, to not only save it inside context, but to make a copy outside of context too, that would be great, like save it in the specified path and also on some other path outside of context.

但我不知道这是否可能,或者如何重现这种行为.

But I don't know if this is possible, or how to reproduce this behaviour.

我需要的是将类代码完全保持原样,但将文件写入 2 次:

首先:/insideContext/mainfolder1/mainsubfolder1/"

然后在这里:/outsideContext/mainfolder1/mainsubfolder1/"

这可能吗?如果不是,那么实现这一目标的最佳方法是什么?

Is this possible? If not, what would be the best way to accomplish this?

推荐答案

我会重构并使用装饰器或包装器模式.更多关于它这里

I'd refactor and use Decorator or Wrapper pattern. More about it here

下面是一些你可以使用的简单想法.

Below some simple idea you could use.

public class ContextAwareDuplicatorOutputStream extends OutputStream {

FileOutputStream insideContext;
FileOutputStream outsideContext;

public ContextAwareDuplicatorOutputStream(String insideContextPath,
        String outsideContextPath, String fileName)
        throws FileNotFoundException {
    insideContext = new FileOutputStream(insideContextPath
            + File.pathSeparator + fileName);
    outsideContext = new FileOutputStream(outsideContextPath
            + File.pathSeparator + fileName);
}

@Override
public void close() throws IOException {
    insideContext.close();
    outsideContext.close();
}

@Override
public void flush() throws IOException {
    insideContext.flush();
    outsideContext.flush();
}

@Override
public void write(byte[] b) throws IOException {
    insideContext.write(b);
    outsideContext.write(b);
}

@Override
public void write(byte[] b, int off, int len) throws IOException {
    insideContext.write(b, off, len);
    outsideContext.write(b, off, len);
}

@Override
public void write(int b) throws IOException {
    insideContext.write(b);
    outsideContext.write(b);
}

}

由于您不想编辑代码中的任何内容,请创建一个 ServletContextListener 来监视您上传的文件夹,并在新文件事件中将其复制到正确的目录.这里介绍了如何监视目录.Java 中的目录侦听器

Since you don't want to edit anything on your code, create a ServletContextListener that monitor the folder where you upload, and on the new file event, you copy it to the proper directory. Here is awnsered how to monitor a directory. Directory listener in Java

下面是一小段代码,虽然不是很完美,但是思路就在那里

Below here is a small code, not really perfect, but the idea is there

public class FileMonitorServletContextListener implements
        ServletContextListener {

    public interface FileMonitor {

        void start(String fromFolder, String toFolder);

        void stop();

    }

    public class SimpleThreadedWatcher implements FileMonitor {

        private class SimpleThread extends Thread {

            private boolean running = true;
            private String fromFolder;
            private String toFolder;

            public SimpleThread(String fromFolder, String toFolder) {
                this.fromFolder = fromFolder;
                this.toFolder = toFolder;
            }

            private void copy(Path child, String toFolder) {
                // Copy the file to the folder
            }

            @Override
            public void run() {
                try {
                    WatchService watcher = FileSystems.getDefault()
                            .newWatchService();
                    Path fromPath = Paths.get(fromFolder);
                    watcher = FileSystems.getDefault().newWatchService();

                    WatchKey key = fromPath.register(watcher,
                            StandardWatchEventKinds.ENTRY_CREATE);

                    while (running) {

                        for (WatchEvent<?> event : key.pollEvents()) {
                            // Context for directory entry event is the file
                            // name of
                            // entry
                            @SuppressWarnings("unchecked")
                            WatchEvent<Path> ev = (WatchEvent<Path>) event;

                            Path name = ev.context();
                            Path child = fromPath.resolve(name);

                            // print out event
                            System.out.format("%s: %s\n", event.kind().name(),
                                    child);

                            copy(child, toFolder);

                            boolean valid = key.reset();
                            if (!valid) {
                                break;
                            }
                        }

                        Thread.sleep(1000);
                    }
                } catch (Exception e) {
                    throw new RuntimeException("Error: ", e);
                }
            }

            public void stopWorking() {
                running = false;
            }

        }

        private SimpleThread worker;

        @Override
        public void start(String fromFolder, String toFolder) {
            worker = new SimpleThread(fromFolder, toFolder);
            worker.start();
        }

        @Override
        public void stop() {
            worker.stopWorking();
        }

    }

    FileMonitor fileMonitor = new SimpleThreadedWatcher();

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        fileMonitor.stop();
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        fileMonitor.start("FROM", "TO");
    }

}

这篇关于覆盖 java.io.FileOutputStream 方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆