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

时间:2016-12-07 22:09:10

标签: java intellij-idea javax.imageio

目前,我正在使用ImageIO.write()来写入文件。但是,这种方法在我的计算机上打开了一个Java App,然后在关闭时强制中止Bootstrap进程,从而杀死了服务器'。我使用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。

非常感谢。

2 个答案:

答案 0 :(得分:1)

  

ImageIO.write()[...]方法在我的计算机上打开一个Java App

这里的问题是当你使用ImageIO类时,由于Java2D类层次结构中的某些依赖性,它也会初始化AWT。这导致OS X上的Java启动程序也在Dock中打开一个图标和其他一些东西,我相信这就是你所经历的。实际上没有新的Java应用程序正在推出。

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

-Djava.awt.headless=true

从Oracle的网页上了解有关headless mode的更多信息。无头模式是跨平台的方式。还有一种OS X / MacOS特定方式可以隐藏停靠栏中的图标(-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(); 
    }
}

答案 1 :(得分:0)

在同时运行多个用户,多次运行该进程等之后,它似乎只是Java的ImageIO或IntelliJ的工件。只要新进程未关闭,即使多个浏览器尝试上传图像等,Bootstrap也会继续正常运行。