java - 使用Java通过HTTP进行图像传输

标签 java serialization

希望 stackoverflow 上的 Java 专家能够指点迷津:

我们通过序列化图像(将其转换为 Java ImageIcon Serialized 类型之后)成功发送图像,但序列化 IO 似乎很昂贵(readObject()、writeObject()),因为我们不断在 servlet 容器中遇到“java.lang.OutOfMemoryError: Java heap space”错误。

有没有更好的方法通过 HTTP 在 Java 中传输图像文件?

该应用程序使用 Java Robot 类通过 servlet 不断地将桌面图像发送到多个客户端(以促进 HTTP 传输)。 听起来已经是个好建议了,让我发布一些代码,让您对我的项目有一个想法。 我必须使用 Java(通过使用 servlet 的网络),我的工作取决于此工作...请帮助...

__添加组件中的关键代码摘录___________

我。客户端小程序 (捕获桌面图像(通过套接字将序列化的图像发送到中央 ImageBroker)

-> 二.图像经纪人 (通过套接字从 ClientApplet 读取序列化图像并 将其发送到 servlet 以使其可供 HTTP 查看器小程序使用)

-> 三.查看器Servlet 通过 HTTP 将图像转发到小程序

-> 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 服务器 代理处理来自不同发送者的图像并将其传输给正确的查看者(通过 servlet) -通过 TCP 套接字从客户端 screensender 小程序接收图像 - 将序列化图像转发到 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();
    }

}
<小时/>

四。 Viewer Applet(连接到Viewer 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 图像输出流中序列化 Bufferedimage,并从输入流的另一端读回它

使用 ImageIO.write 对其进行序列化,并使用 ImageIO.read 对其进行反序列化。

http://docs.oracle.com/javase/6/docs/api/javax/imageio/ImageIO.html

安东尼

关于java - 使用Java通过HTTP进行图像传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9549301/

相关文章:

java - Graphics.drawimage 不工作 Java 8

java - Akka Actor 一次处理一条消息

c# - 将具有多个元素的 XML 反序列化为单个 C# 对象

c# - 使用 Json.NET 将 JSON 反序列化为对象

java - 如何使用 OpenOffice Java API 更新 Word 文档中嵌入的 Excel 表格?

java - @SpringBootTest 用于非 spring-boot 应用程序

java - TextView 未在 Android 中更新

serialization - 戈朗 : print struct as it would appear in source code

python - 如何以人类可读的方式将 python 字典序列化为文本?

python - 如何在 Django Rest Framework 序列化器中访问初始数据