Reputation: 2196
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.
Upvotes: 4
Views: 577
Reputation: 2196
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!
Upvotes: 2
Reputation: 45555
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");
}
Upvotes: 2