What is the delay between sending HttpPost to server and server

I download the zip file from the Java desktop application to Httpserver (running Tomcat 7), I use Apache httpClient 4.5.3, and I show a progress bar showing progress using this shell solution https://github.com/x2on/gradle-hockeyapp -plugin / blob / master / src / main / groovy / de / felixschulze / gradle / util / ProgressHttpEntityWrapper.groovy

So in my code Im updating the progress indicator every time the called call is called

HttpEntity reqEntity = MultipartEntityBuilder.create()
        .addPart("email", comment)
        .addPart("bin", binaryFile)
        .build();

ProgressHttpEntityWrapper.ProgressCallback progressCallback = new ProgressHttpEntityWrapper.ProgressCallback() {

    @Override
    public void progress(final float progress) {
        SwingUtilities.invokeLater(
                new Runnable()
                {
                    public void run()
                    {
                        MainWindow.logger.severe("progress:"+progress);
                        Counters.getUploadSupport().set((int)progress);
                        SongKong.refreshProgress(CreateAndSendSupportFilesCounters.UPLOAD_SUPPORT_FILES);
                    }
                }
        );
    }
};

httpPost.setEntity(new ProgressHttpEntityWrapper(reqEntity, progressCallback));
HttpResponse response = httpclient.execute(httpPost);
HttpEntity resEntity = response.getEntity();
MainWindow.logger.severe("HttpResponse:"+response.getStatusLine());

Sends files downloaded as a percentage, but there is a significant delay between them between 100% creation and the actual receipt of http status from the server.

07/07/2017 14.23.54:BST:CreateSupportFile$4$1:run:SEVERE: progress:99.19408
07/07/2017 14.23.54:BST:CreateSupportFile$4$1:run:SEVERE: progress:99.40069
07/07/2017 14.23.54:BST:CreateSupportFile$4$1:run:SEVERE: progress:99.6073
07/07/2017 14.23.54:BST:CreateSupportFile$4$1:run:SEVERE: progress:99.81391
07/07/2017 14.23.54:BST:CreateSupportFile$4$1:run:SEVERE: progress:99.99768
07/07/2017 14.23.54:BST:CreateSupportFile$4$1:run:SEVERE: progress:99.99778
07/07/2017 14.23.54:BST:CreateSupportFile$4$1:run:SEVERE: progress:99.99789
07/07/2017 14.23.54:BST:CreateSupportFile$4$1:run:SEVERE: progress:99.999794
07/07/2017 14.23.54:BST:CreateSupportFile$4$1:run:SEVERE: progress:99.9999
07/07/2017 14.23.54:BST:CreateSupportFile$4$1:run:SEVERE: progress:100.0
07/07/2017 14.24.11:BST:CreateSupportFile:sendAsHttpPost:SEVERE: HttpResponse:HTTP/1.1 200 OK
07/07/2017 14.24.11:BST:CreateSupportFile:sendAsHttpPost:SEVERE: Unknown Request

- , tomcat , tomcat , " ".

protected void doPost(javax.servlet.http.HttpServletRequest request, 

    javax.servlet.http.HttpServletResponse response)
                throws javax.servlet.ServletException, java.io.IOException
        {
            String createMacUpdateLicense   = request.getParameter(RequestParameter.CREATEMACUPDATELICENSE.getName());
            if(createMacUpdateLicense!=null)
            {
                createMacUpdateLicense(response, createMacUpdateLicense);
            }
            else
            {
                response.setCharacterEncoding("UTF-8");
                response.setContentType("text/plain; charset=UTF-8; charset=UTF-8");
                response.getWriter().println("Unknown Request");
                response.getWriter().close();
            }
        }

Update serveride,

    @Override
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
            throws javax.servlet.ServletException, java.io.IOException
    {
        String uploadSupportFiles   = request.getParameter(RequestParameter.UPLOADSUPPORTFILES.getName());
        if(uploadSupportFiles!=null)
        {
            uploadSupportFiles(request, response, uploadSupportFiles);
        }
        else
        {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/plain; charset=UTF-8; charset=UTF-8");
            response.getWriter().println("Unknown Request");
            response.getWriter().close();
        }
    }

private void uploadSupportFiles(HttpServletRequest request, HttpServletResponse response, String email) throws IOException
    {
        Part filePart;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/plain; charset=UTF-8; charset=UTF-8");

        try
        {
            filePart = request.getPart("bin");
            String fileName = getSubmittedFileName(filePart);
            response.getWriter().println(email+":File:" + fileName);

            //Okay now save the zip file somewhere and email notification
            File uploads = new File("/home/jthink/songkongsupport");
            File supportFile = new File(uploads, email+".zip");

            int count =0;
            while(supportFile.exists())
            {
                supportFile = new File(uploads, email+"("+count+").zip");
                count++;
            }
            InputStream input;
            input = filePart.getInputStream();
            Files.copy(input, supportFile.toPath());

            Email.sendAlert("SongKongSupportUploaded:" + supportFile.getName(),  "SongKongSupportUploaded:" + supportFile.getName());
            response.getWriter().close();
        }
        catch(ServletException se)
        {
            response.getWriter().println(email+":"+se.getMessage());
            response.getWriter().close();
        }


    }
+4
2

, - - "DONE", , :

Bytes written to socket OutputStream
============================|
<--> Buffering              |
    Bytes sent by TCP stack |
    ============================
    <------> Network latency|
            Bytes received by Tomcat
            ============================
                            |           (Tomcat waits for all data to finish uploading
                            |            before handing it out as "parts" for your code)  
                            |            File written to local file on server
                            |            =====
                            |                
                            |                  Response "DONE" written by servlet to socket output
                            |                  ==
                            |                  <---> Network latency 
                            |                       == Response "DONE" received by client
                            |                         |
                            |                         |
  "100%" for entity wrapper ^             Actual 100% ^
                             Discrepancy
                             <----------------------->
                             "Twilight Zone" : part of discrepancy you cannot do much about.
                             (progress feedback impossible without using much lower level APIs)
                             <--------------------->

, , , , , .

, .

, :

  • ( ) (, ) / Java
  • () (, ) / Java
  • ( ) zip
  • ()
  • ( ) ()

, "upload complete" 90% 90 100, . 0% 90% "Uploading", , "...", , throbber, , 100%.

, . , , "" 100% ( ), .

" " , , , , " ?" ( ). , , ( , ).


/ , . , API (, @MultipartConfig ..), - ( ), , 1% , ( , , ). . , , :

  • POST, , 90% (.. 50%, 45%)
  • , 91%, 95%, , 100%.

, ( 100% , ), , , ( 90% , 91/92/... 99/100 ).

, , . 17 , , , - . , , , 50 , - , .

+3

, , . , 10 , 1 . 10 1 . . , Javascript. HttpRequest , . , plupload, , .

, , Web-, JSON . javascript JSON . , , . Javascript - , , . plupload , , , , .

protected void Upload()
{
    HttpPostedFile file = Request.Files[0];
    String relativeFilePath = "uploads/";
    try
    {
        if(file == null)
            throw new Exception("Invalid Request.");
        //plupload uses "chunk" to indicate which chunk number is being sent
        int chunk = (int)Request.Form["chunk"];
        //plupload uses "chunks" to indicate how many total chunks are being sent
        int chunks = (int)Request.Form["chunks"];
        //plupload uses "name" to indicate the original filename for the file being uploaded
        String filename = Request.Form["name"];
        relativeFilePath += filename;


        //Create a File Stream to manage the uploaded chunk using the original filename
        //Note that if chunk == 0, we are using FileMode.Create because it is the first chunk
        //otherwise, we use FileMode.Append to add to the byte array that was previously saved
        using (FileStream fs = new FileStream(Server.MapPath(relativeFilePath), chunk == 0 ? FileMode.Create : FileMode.Append))
        {
           //create the byte array based on the data uploaded and save it to the FileStream
           var buffer = new byte[file.InputStream.Length];
           file.InputStream.Read(buffer, 0, buffer.Length);
           fs.Write(buffer, 0, buffer.Length);
        }

        if((chunks == 0) || ((chunks > 0)&&(chunk == (chunks - 1))))
        {
          //This is final cleanup.  Either there is only 1 chunk because the file size
          //is less than the chunk size or there are multiple chunks and this is the final one
          //At this point the file is already saved and complete, but maybe the path is only
          //temporary and you want to move it to a final location
          //in my code I rename the file to a GUID so that there is never a duplicate file name
          //but that is based on my application needs
          Response.Write("{\"success\":\"File Upload Complete.\"}");
        }
        else
          Response.Write("{\"success\":\"Chunk "+chunk+" of "+chunks+" uploaded.\"}");
    }
    catch(Exception ex)
    {
        //write a JSON object to the page and HtmlEncode any quotation marks/HTML tags
        Response.Write("{\"error\":\""+HttpContext.Current.Server.HtmlEncode(ex.Message)+"\"});
    }
}
0

Source: https://habr.com/ru/post/1680972/


All Articles