代码之家  ›  专栏  ›  技术社区  ›  user1305398

流式Rest Api—以数据块的形式从restful Api以流的形式向客户端发送数据

  •  1
  • user1305398  · 技术社区  · 7 年前

    我需要创建一个流rest api来读取文件。我们正在构建类似于 linux命令。

    如果用户输入 ccat filename | tail,然后我们必须保持流的打开状态,以256字节的块读取内容,并等待资源从客户端关闭。

    我已经创建了一个POC。rest api代码如下所示-

    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    @RequestMapping(method = RequestMethod.GET, value = "stream")
    public void hello(@Context HttpServletRequest request, @Context HttpServletResponse response)
      throws InterruptedException {
    String content = "This is the text content";
    ServletOutputStream outputStream = null;
    try {
      for(int i=0;i<100;i++){
        content = content + i;
        final byte[] bytes = content.getBytes();
        outputStream = response.getOutputStream();
        response.setContentType("application/octet-stream");
        response.setStatus(200);
        outputStream.write(bytes);
        Thread.sleep(1000l);
        outputStream.flush();
      }
    
      outputStream.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
    

    客户端代码如下-

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    
    public class NetClientGet {
    public static void main(String[] args) {
    
    try {
    
      URL url = new URL("http://localhost:6868/api/stream");
      HttpURLConnection conn = (HttpURLConnection) url.openConnection();
      conn.setRequestMethod("GET");
      conn.setRequestProperty("Accept", "application/json");
      if (conn.getResponseCode() != 200) {
        throw new RuntimeException("Failed : HTTP error code : "
            + conn);
      }
      BufferedReader br = new BufferedReader(new InputStreamReader(
          (conn.getInputStream())));
      String output;
      System.out.println("Output from Server .... \n");
      while ((output = br.readLine()) != null) {
        System.out.println(output);
      }
      conn.disconnect();
    } catch (MalformedURLException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    }
    }
    

    这工作很好,但问题是它并不是一次性写入字节块,而是一次性写入整个内容。我正在调用flush(),所以我希望它在每次调用flush()时都会将块发送给客户端,但这似乎没有发生。它在调用close()后发送到客户端。我怎样才能解决这个问题?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Osama Khalifa    3 年前

    我认为在这个用例中使用java套接字会更好。