java - 文件在没有缓冲的情况下流式传输良好,但在缓冲时部分流式传输

标签 java servlets streaming httpurlconnection buffering

我编写了一段代码,将字节从另一台服务器流式传输到我的服务器,然后将这些内容写入本地文件。当我使用不缓冲数据的 read() 方法时,它工作正常。但是当我使用缓冲时(目的是我相信对于大文件来说流式传输会更快)我使用 read(byte[]) 方法,并且它在流式传输时仅获取部分数据。我正在发布代码。任何人都可以指出我所缺少的错误或概念吗?

下面的代码工作正常。 (无流媒体)

    private void doViewDocument(HttpServletRequest request,
            HttpServletResponse response, DocumentServletService servletService) throws GEMException, MalformedURLException, ProtocolException, IOException {

        final String objectID = request.getParameter(PARAM_OBJECT_ID);

        LOGGER.info("For Viewing Document objectID received from Request == " + objectID);

        if (GEMSharedUtil.isValidObjectId(objectID)) {

            String ebesDocDownloadURL = servletService.getDocumentDownloadUrl(objectID);

            if (!GEMSharedUtil.isValidString(ebesDocDownloadURL)) {             
                //response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
                response.setHeader("ResponseStatus", "Not_OK");
                throw new GEMException();
            } else {
                HttpURLConnection con = null;
                BufferedInputStream bin = null;
                BufferedOutputStream bout = null;

                try {
                    con = (HttpURLConnection) new URL(ebesDocDownloadURL).openConnection();

                    WASSecurity.preauthenticateWithLTPACookie(con);
                    con.setRequestMethod(REQUEST_METHOD_GET);
                    con.setDoOutput(true); // Triggers POST but since we have set request method so it will override it
                    con.setDoInput(true);
                    con.setUseCaches(false);
                    con.setRequestProperty("Connection", "Keep-Alive");
                    con.setAllowUserInteraction(false);
                //  con.setRequestProperty("Content-Type",
                //  "application/octet-stream");

                    response.setBufferSize(1024);
                    response.setContentType(con.getContentType());
                    response.setContentLength(con.getContentLength());
                    response.setHeader("ResponseStatus", "OK");
                    response.setHeader("Content-Disposition", con
                            .getHeaderField("Content-Disposition"));

                    bin = new BufferedInputStream((InputStream)
                            con.getInputStream(), 1024);

                    bout = new BufferedOutputStream(
                            response.getOutputStream(), 1024);

                    byte[] byteRead = new byte[1024];


                    File file = new File("C:\\Documents and Settings\\weakStudent\\Desktop\\streamed\\testStream.pdf");

                    FileOutputStream fos = new FileOutputStream(file);

                    if(file.length() > 0) {
                        file.delete();
                    }
                    file.createNewFile();

                    BufferedOutputStream fbout = new BufferedOutputStream((OutputStream) fos);
                    int c;
                    while((c= bin.read()) != -1) {
                        bout.write(c);
                        fbout.write(c);
                    }
fos.close();
                    bout.flush();
                    fbout.flush();
                    fbout.close();
                    LOGGER.info("con.getResponseCode():" + con.getResponseCode());

                } finally {
                    try {
                        if (bout != null) {
                            bout.close();
                        }
                    } catch (IOException e) {
                        LOGGER.log(Level.SEVERE, e.getMessage(), e);
                        throw new RuntimeException(e);
                    } finally {
                        try {
                            if (bin != null) {
                                bin.close();
                            }
                        } catch (IOException e) {
                            LOGGER.log(Level.SEVERE, e.getMessage(), e);
                            throw new RuntimeException(e);
                        } finally {
                            if (con != null) {
                                con.disconnect();
                            }
                        }
                    }
                }
            }

        }   //if ends

    }

现在,如果我有以下 while 循环,它就无法正常工作。

                while(bin.read(byteRead) != -1) {
                    bout.write(byteRead);
                    fbout.write(byteRead);
                }

第二季度) 还想知道是否必须使用 BufferedInputStream/BufferedOutputStream 进行流式处理。例如,如果我使用以下代码片段,它就可以工作

    BufferedInputStream bin = null;

    try {
        //in = request.getInputStream();        

        bin = new BufferedInputStream((InputStream) request
                .getInputStream(), 1024);

        int respcode = HttpURLConnection.HTTP_OK;
        con = createConnection(uploadURL, REQUEST_METHOD_POST);
        con.setRequestProperty("X-File-Name",fileName);

        conOut = con.getOutputStream();
        bout = new BufferedOutputStream(conOut);
        byte[] byteRead = new byte[1024];       

        while (bin.read(byteRead) != -1) {
            bout.write(byteRead);
        }
        bout.flush(); 
        respcode = con.getResponseCode();    

但以下内容再次部分流式传输(此处未使用 BufferedInputStream)

    ServletInputStream in = null;

    try {
        in = request.getInputStream();      

        int respcode = HttpURLConnection.HTTP_OK;
        con = createConnection(uploadURL, REQUEST_METHOD_POST);
        con.setRequestProperty("X-File-Name",fileName);

        conOut = con.getOutputStream();
        bout = new BufferedOutputStream(conOut);
        byte[] byteRead = new byte[1024];       

        while (in.read(byteRead) != -1) {
            bout.write(byteRead);
        }
        bout.flush(); 
        respcode = con.getResponseCode();    

最佳答案

A1。您丢弃已读取的字节数,告诉输出流写入 byteRead 缓冲区的全部内容,其中可能包含先前读取的数据

int bytesIn = -1;
while((bytesIn = bin.read(byteRead)) != -1) {
    bout.write(byteRead, 0, bytesIn);
    fbout.write(byteRead, 0, bytesIn);
}

更新 基本上,您的所有示例都遇到相同的问题。你的缓冲区有n个字节长,但是读取可以在缓冲区中返回0到n个字节,你需要记下read方法返回的字节数才能知道要写入多少

关于java - 文件在没有缓冲的情况下流式传输良好,但在缓冲时部分流式传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11448809/

相关文章:

java - ObjectInputStream 抛出 EOFException

Java转换编码

java - 即使发送了属性,JSP 代码也显示 null

java - 从 Servlet 调用 Jasper iReport

audio - 使用 FFMPEG 将可搜索的 AAC 音频流写入 MP4 文件

java - 如何强制 EclipseLink 的 @PrivateOwned 在插入前执行删除

java - 在 AspectJ 中禁用/避免建议执行

java - 以编程方式将 HttpSessionListener 添加到 Jetty 不起作用

streaming - 与 SHOUTcast 一起使用的网络播放器

java - 如何连续播放AudioInputStream的音频?