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();
}
}
目前,我正在使用 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();
}
}