RESTful 服务器应该如何将用户提交的图像保存到文件中?

How should a RESTful server save user submitted images to file?

目前,我正在使用 ImageIO.write() 来写入文件。但是,此方法会在我的计算机上打开一个 Java 应用程序,如果关闭,该应用程序会强制中止 Bootstrap 进程,从而杀死 'server'。我正在使用 IntelliJ 在本地进行测试,Bootstrap 进程的终止意味着我们无法在不重新启动服务器的情况下测试功能。

我的方法如下。它在来自我们前端的 API 调用上运行。

/**
 * Saves image to database, assuming that the input is not null or empty.
 * @param filename name of file.
 * @param fileext extension of file.
 * @param uri uri in string form.
 */
public static void saveImageToDisk(String filename, String fileext, String uri) {
    try {
        String[] components = uri.split(",");
        String img64 = components[1];
        byte[] decodedBytes = DatatypeConverter.parseBase64Binary(img64);
        BufferedImage bfi = ImageIO.read(new ByteArrayInputStream(decodedBytes));    
        File outputfile = new File(IMAGESTORAGEFOLDER + filename + "." + fileext);
        ImageIO.write(bfi, fileext, outputfile);
        bfi.flush();
    } catch(Exception e) {  
        e.printStackTrace(); 
    }
}

我的问题如下:如何在服务器不中止的情况下将图像(来自原始数据)保存到文件?如果我的代码可以通过最少的重写进行调整,我还可以做哪些其他改进来加强我现有的代码?我想要一个没有外部依赖性的解决方案(完全依赖于标准 Java 库)。

我在 MacOSX,运行IntelliJ IDEA CE。我们的服务器使用 Spark 运行并使用 Maven。

非常感谢。

在运行同时多个用户、运行多次处理该过程等之后,它似乎只是 Java 的 ImageIO 或IntelliJ。只要新进程不关闭,Bootstrap继续正常运行,即使多个浏览器尝试上传图片等

ImageIO.write() [...] method opens up a Java App on my computer

这里的问题是,当您使用 ImageIO class 时,由于 Java2D class 层次结构中的某些依赖关系,它还会初始化 AWT。这会导致 OS X 上的 Java 启动器也在 Dock 中打开一个图标和其他一些东西,我相信这就是您的体验。确实没有启动新的 Java 应用程序。

您可以通过在启动时将系统 属性 传递给 Java 启动器,并在 "headless" 模式下告诉它 运行 来轻松避免这种情况。这通常适用于服务器进程。在命令行(或 IntelliJ 启动对话框中)传递以下内容:

-Djava.awt.headless=true

从 Oracle 页面阅读更多关于 headless mode 的信息。无头模式是执行此操作的跨平台方式。还有一个 OS X/MacOS 特定的方法来从 dock 中隐藏图标(-Dapple.awt.UIElement=true,但我不推荐在这里。

但是,对于您的用例,最好完全避免使用 ImageIO。 它更容易、更兼容、更快,并且使用更少的内存作为奖励。只需将 Base64 解码后的字节直接写入磁盘即可。在这种情况下,无需将包含图像的文件与任何其他文件区别对待。

您可以按如下方式重写您的方法:

public static void saveImageToDisk(String filename, String fileext, String uri) {
    try {
        String[] components = uri.split(",");
        String img64 = components[1];
        byte[] decodedBytes = DatatypeConverter.parseBase64Binary(img64);
        File outputfile = new File(IMAGESTORAGEFOLDER, filename + "." + fileext);
        Paths.write(outputFile.toPath(), decodedBytes);
    } catch(Exception e) {  
        // You really shouldn't swallow this exception, but I'll leave that to you...
        e.printStackTrace(); 
    }
}