无需缓冲即可很好地流式传输文件,但在缓冲时可部分流式传输 [英] File Streamed well without buffering but gets streamed partially while buffering

查看:227
本文介绍了无需缓冲即可很好地流式传输文件,但在缓冲时可部分流式传输的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have written a code which streams bytes from another server to my server and then I write those contents into my local file. It works fine when I use the read() method which doesn't buffer data. But when I use buffering (intention is that I believe streaming would be faster for big files) I use read(byte[]) method and it gets only partial data while streaming. I am posting the code. Can any one pls point out the mistake or concepts what I am missing.

以下代码可以正常工作. (无流式播放)

The following code works fine. (no streaming)

    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循环,它将无法正常工作.

Now if I have the following while loop it doesn't work correctly.

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

第二季度 还想知道是否必须使用BufferedInputStream/BufferedOutputStream进行流传输.例如,如果我使用以下代码片段,则可以正常工作

Q2) Also would like to know is it mandatory to use BufferedInputStream/BufferedOutputStream for streaming. For eg if I use following code snippet it works

    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)

But the following again streams partially (no BufferedInputStream used here)

    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缓冲区的全部内容,其中可能包含上次读取的数据

A1. Your discarding the number of bytes that were read, telling the output stream to write the entire contents of byteRead buffer, which may contain data from the previous read

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

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

UPDATE Basically, all your examples are suffering from the same problem. Your buffer is n bytes long, but the read can return 0 to n bytes in the buffer, you need to take note of the number of bytes the read method returns in order to know how much to write

这篇关于无需缓冲即可很好地流式传输文件,但在缓冲时可部分流式传输的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆