4

I have a Struts 2 Action, and Struts 2 is at SERVER SIDE, to allow user to download files from my application.

The files are stored inside a database (I know... but keep the focus). The user access the action, I get the file from database and send to user by using a Stream.

@Action(value="getFile", results= {  
        @Result(name="ok", type="stream", params = {
                "contentType", "application/octet-stream",
                "inputName", "fileInputStream",
                "contentDisposition", "filename=\"${fileName}\"",
                "bufferSize", "1024"
        }) }
)  

...

public class GetFileAction {
    private String fileName;
    private Integer idFile;
    private ByteArrayInputStream fileInputStream;

    public String execute () {
            ...
            try {
                FileService fs = new FileService();
                if ( (idFile != null) && ( idFile > -1 ) ) {
                    file = fs.getFile( idFile );
                }

                if ( file != null ) {
                    byte[] theFile = file.getFile();

                    fileInputStream = new ByteArrayInputStream( theFile );
                    fileName = file.getFileName();
                } else {
                    //
                }

            } catch ( Exception e ) {
                //
            }
...

All is working as I wish, but I want to monitor ( from my Tomcat container - SERVER SIDE, not the user's browser ) from server side the progress of user download ...

Is it possible?

Thanks.

Magno C
  • 1,922
  • 4
  • 28
  • 53
  • There's already question like [this](http://stackoverflow.com/q/28061516/573032). – Roman C Jun 27 '15 at 12:22
  • @RomanC doesn't seems to be a duplicate as he wants to monitor download from the server side – Alireza Fattahi Jun 27 '15 at 14:16
  • @AlirezaFattahi It seems he can't monitor it when the browser downloads, so you need to create a component that will show the progress of downloading the file. The file is downloading from the server but the component supposed to be on the client otherwise it's called the logging. – Roman C Jun 27 '15 at 17:16
  • @RomanC the question you pointed as my duplicate is using javascript, so its client side. Is not my case. – Magno C Jun 28 '15 at 16:07
  • @MagnoC What is he using doesn't matter, but this question will be closed because there's already a question like this which have an answer. – Roman C Jun 28 '15 at 16:53
  • 2
    And where is this question? Javascript IS CLIENT side, so its matter. I want to monitor the download at SERVER side. Alireza Fattahi understood this and I'll accept the answer as soon as I can test it. Please see his answer and you will see the difference between server and client side download monitoring. If I download not using a client browser (like a Java program) how can I apply the answer pointed by you and how can I monitor the various clients downloads at server side (like your machine do when you seed a torrent file to multiple clients)? – Magno C Jun 28 '15 at 17:25
  • Someone please remove the "Duplicated" mark because it can confusing users and send they to wrong answers. Thanks. – Magno C Jun 29 '15 at 12:07
  • I liked everything of this Q&A, +1 to everybody :P – Andrea Ligios Jun 29 '15 at 15:33

2 Answers2

2

If you want to monitor the user download on your server then you need to define your own stream result type. As the struts stream result class doesn't log or generate these data.

You can extend the StreamResult. Please have a look at doExecute method. You can see

 while (-1 != (iSize = inputStream.read(oBuff))) {
                oOutput.write(oBuff, 0, iSize);
  }

Here you can find how much data is read from your file. You may put some logs here. The while loops repeats for every buffer size ( which is 2048 by default). A simple counter in this loop will show you how much data you have read

 int totalBlock = 0 ;
 while (-1 != (iSize = inputStream.read(oBuff))) {
           oOutput.write(oBuff, 0, iSize);
           totalBlock ++;
          log.debug( totalBlock * 2048  + "  is read so far");
      }
Alireza Fattahi
  • 42,517
  • 14
  • 123
  • 173
2

Ok guys. I found the trick here:

http://www.java2s.com/Code/Android/File/InputStreamthatnotifieslistenersofitsprogress.htm

Just implemented my own listener:

public class ProgressListener implements OnProgressListener {

    @Override
    public void onProgress(int percentage, Object tag) {
        System.out.println( (String)tag + " " + percentage + "%" );

    }

}

And changed my Struts 2 Action to:

@Action(value="getFile", results= {  
        @Result(name="ok", type="stream", params = {
                "contentType", "application/octet-stream",
                "inputName", "fileInputStream",
                "contentDisposition", "filename=\"${fileName}\"",
                "bufferSize", "1024"
        }) }
)   

@ParentPackage("default")
public class GetFileAction extends BasicActionClass {
    private String fileName;
    private Integer idFile;
    private ProgressAwareInputStream fileInputStream;

    public String execute () {
        cmabreu.sagitarii.persistence.entity.File file = null;

        try {
            FileService fs = new FileService();
            if ( (idFile != null) && ( idFile > -1 ) ) {
                file = fs.getFile( idFile );
            }

            if ( file != null ) {
                fileName = file.getFileName();
                byte[] theFile = file.getFile();

                ProgressAwareInputStream pais = new ProgressAwareInputStream( new ByteArrayInputStream( theFile ), 
                        theFile.length, fileName );

                pais.setOnProgressListener( new ProgressListener() );

                fileInputStream = pais; 

            } else {
                //
            }

        } catch ( Exception e ) {
            //
        }

        return "ok";
    }

    ... getters and setters .

}

And the result when I go to http://myapplication:8080/getFile?idFile=1234 was printed on Tomcat console (for now):

6FB377291.g6.txt.dot.gif 21%
6FB377291.g6.txt.dot.gif 42%
6FB377291.g6.txt.dot.gif 63%
6FB377291.g6.txt.dot.gif 84%
6FB377291.g6.txt.dot.gif 100%

Sounds perfect to me!

Magno C
  • 1,922
  • 4
  • 28
  • 53