[英]Image transmission over HTTP with Java
希望Stackoverflow中的Java專家可以闡明一些觀點:
我們已經通過序列化圖像成功地發送了圖像(將其轉換為Java ImageIcon Serializable類型之后),但是序列化的IO似乎很昂貴(readObject(),writeObject()),因為我們不斷遇到“ java.lang.OutOfMemoryError:Java堆” servlet容器中出現“空格”錯誤。
是否有更好的方法通過HTTP在Java中傳輸圖像文件?
該應用程序使用Java Robot類通過servlet將桌面圖像連續發送到多個客戶端(以促進HTTP傳輸)。 聽起來已經是很好的建議,讓我發布一些代碼,為您的項目做個主意。 我必須使用Java(在使用servlet的Web上),而我的工作取決於此工作……請幫助...
__ 從組件中添加關鍵代碼節選 __ _ __ _ __ _ __
I. ClientApplet(捕獲桌面圖像(通過套接字序列化發送到中央ImageBroker)
-> II。 ImageBroker(通過套接字從ClientApplet讀取序列化的圖像,並將其發送到servlet,以使其可用於HTTP查看器小程序)
-> III。 ViewerServlet通過HTTP將圖像轉發到applet
-> IV.Applet讀取序列化圖像
// I. Client Applet
// (sends serialized desktop images to ImageBroker server over TCP sockets )
class ScreenShoot extends Thread {
Socket socket = null;
Robot robot = null; // Used to capture screen
Rectangle rectangle = null; //Used to represent screen dimensions
boolean continueLoop = true; //Used to exit the program
public ScreenShoot(Socket socket, Robot robot, Rectangle rect) {
this.socket = socket;
this.robot = robot;
rectangle = rect;
start();
}
public void run() {
ObjectOutputStream oos = null; //Used to write an object to the streem
try {
//Prepare ObjectOutputStream
oos = new ObjectOutputStream(socket.getOutputStream());
} catch (IOException ex) {
ex.printStackTrace();
}
String Userid = "test";
String ConfId = "ONE";
MyClass sendHeader = new MyClass(Userid,ConfId, 300, 300, 20, 30);
System.out.println("sendHeader: " + sendHeader);
// Send the header (username, ConferenceID) first before sending the images
try {
oos.writeObject(sendHeader);
System.out.println("sent HEADER object1: ");
} catch (IOException ex) {
ex.printStackTrace();
}
int countRec = 1;
while (continueLoop) {
//Capture screen
BufferedImage image = robot.createScreenCapture(rectangle);
/* I have to wrap BufferedImage with ImageIcon because BufferedImage class
* does not implement Serializable interface
*/
ImageIcon imageIcon = new ImageIcon(image);
//Send captured screen to the server
try {
System.out.println("ScreenSpyer:before sending image-writeObject");
// oos.writeObject(imageIcon);
oos.writeUnshared(imageIcon);
countRec++;
if (countRec > 20 ) {
oos.reset(); //Clear ObjectOutputStream cache
countRec = 1;
}
System.out.println("ScreenSpyer: New screenshot sent");
} catch (IOException ex) {
ex.printStackTrace();
}
//wait for 1000ms to redu/ e network traffic
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
II.Central ImageBroker Server Broker處理來自不同發件人的圖像並將其傳輸到正確的查看器(通過Servlet)-通過TCP套接字從客戶端屏幕發送器小程序接收圖像-將序列化的圖像轉發到ViewerServlet
// Section READING the incoming images ( this is over simple TCP Sockets)
class HandleSenders extends Thread {
private Socket socket = null;
private WinTest mainprog;
private MessageBin source;
private InputStream fromServer = null;
public HandleSenders(WinTest mainprog, Socket socket, MessageBin source) {
super("HandleSenders");
this.socket = socket;
this.mainprog = mainprog;
this.source = source;
}
// getNextMessage() returns the next new message.
// It blocks until there is one.
public String getNextMessage() {
// Create a message sink to wait for a new message from the
// message source.
return new MessageHold().getNextMessage(source);
}
public void run() {
// Reading Images from SnreenSender client
ObjectInputStream in = null;
byte[] buffer = new byte[256];
int fromServer_val, backup_val =0 ;
try {
// in = new ObjectInputStream(socket.getInputStream());
fromServer = socket.getInputStream();
in = new ObjectInputStream(fromServer);
boolean forever = true;
int cntr = 1;
boolean contin = true;
int counter = 1;
boolean Found = false;
String theMessage = "";
while (contin) {
// if (cntr++ > 5) break;
// fromServer_val = fromServer.read(buffer);
// dealing with null values which crashes the system,
// if for some problem in transmission you get a null, we just put the
// previous valid data
// into the null one.
ImageIcon imageIcon = (ImageIcon)in.readObject();
Found = mainprog.FindViewersAndSend(senderHeader.confid, imageIcon);
// Blocks first time and only if the structure has no
// clients for this sender
if (!Found)
theMessage = getNextMessage(); //blocks
將圖像發送到servlet的部分處理
public boolean FindViewersAndSend(String confid, ImageIcon imageIcon) {
Iterator it = socketMap.entrySet().iterator();
ObjectOutputStream viewerOut = null;
byte[] buffer = new byte[256];
Socket viewerClient = null;
OutputStream toClient = null;
boolean Found = false;
int recordCount = 1;
try {
while (it.hasNext()) {
// Iterating through structures of Viewer servlet socket connections
Map.Entry pairs = (Map.Entry)it.next();
socketUserStruct = getSocketDetails((String)pairs.getKey());
if ( socketUserStruct != null && !socketUserStruct.equals ("")) {
StructConfId = (String)socketUserStruct.getConfId();
StructUserId = (String)pairs.getKey();
}
if (StructConfId.equals(confid)) {
Found = true;
viewerOut = (ObjectOutputStream)socketUserStruct.getObjectOutputStream();
// write the serialized data to the servlet....
// which in turn sends it to the applet over http
// viewerOut.writeObject(imageIcon);
viewerOut.writeUnshared(imageIcon);
recordCount++;
if (recordCount > 10) {
viewerOut.flush();
recordCount = 0;
}
}
}
}
catch (IOException e)
{ /// clean up
removeSocketClient(StructUserId);
}
return Found;
}
三, ViewerServlet-從圖像代理獲取圖像並將序列化的圖像發送到Applet(通過http)
public void doGet(HttpServletRequest req,
HttpServletResponse res) throws ServletException,
Socket echoSocket = null;
PrintWriter out = null;
InputStream fromServer = null;
byte[] buffer = new byte[256];
int fromServer_val, backup_val = 0;
// OutputStream toClient = res.getOutputStream();
try {
echoSocket = new Socket("localhost", RES_PORT);
out = new PrintWriter(echoSocket.getOutputStream(), true);
String screensize = "300";
String viewerHeader = userid+","+confid+","+screensize;
out.println(viewerHeader);
out.println("bye");
out.flush();
InputStream is = echoSocket.getInputStream();
ObjectInputStream in = new ObjectInputStream(is);
ObjectOutputStream oos = new ObjectOutputStream(res.getOutputStream());
try {
int recordCount = 1;
while (true) {
ImageIcon imageIcon = (ImageIcon)in.readObject();
oos.writeObject(imageIcon);
if (recordCount++ > 5) {
recordCount = 1;
oos.flush();
}
// oos.flush();
}
} catch (ClassNotFoundException e) {
.......
} catch (IOException ex) {
ex.printStackTrace();
}
} catch (IOException e) { // show("plainViewAdapter-doGet:4");
fromServer.close();
}
}
IV。 查看器小程序(連接到查看器Servlet以接收圖像)
public void start() {
try {
String url_string =
"http://" + winsellahost + ":" + winsellaport + "/BrowserShare
/viewerproxyservlet" +
"?userid=viewer1&confid=ONE";
URL url = new URL(url_string);
InputStream is = url.openConnection().getInputStream();
ObjectInputStream in = new ObjectInputStream(is);
boolean firstTime = true;
while (continueLoop) {
show("5");
//Recve client screenshot and resize it to the current panel size
ImageIcon imageIcon = (ImageIcon)in.readObject();
// in.reset();
Image image = imageIcon.getImage();
image =
image.getScaledInstance(cPanel.getWidth(), cPanel.getHeight(),
Image.SCALE_FAST);
//Draw the received screenshot
}
in.close();
is.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
不要序列化為對象。
在PNG圖像OutputStream中序列化Bufferedimage,然后從InputStream的另一面讀回
使用ImageIO.write對其進行序列化,並使用ImageIO.read對其進行反序列化。
http://docs.oracle.com/javase/6/docs/api/javax/imageio/ImageIO.html
安東尼
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.