I upload multiple files to Amazon S3 using Java.
I am using the following code:
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; MultiValueMap < String, MultipartFile > map = multipartRequest.getMultiFileMap(); try { if (map != null) { for (String filename: map.keySet()) { List < MultipartFile > fileList = map.get(filename); incrPercentge = 100 / fileList.size(); request.getSession().setAttribute("incrPercentge", incrPercentge); for (MultipartFile mpf: fileList) { ProgressInputStream inputStream = new ProgressInputStream("test", mpf.getInputStream(), mpf.getBytes().length); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType(mpf.getContentType()); String key = Util.getLoginUserName() + "/" + mpf.getOriginalFilename(); PutObjectRequest putObjectRequest = new PutObjectRequest( Constants.S3_BUCKET_NAME, key, inputStream, metadata).withStorageClass(StorageClass.ReducedRedundancy); PutObjectResult response = s3Client.putObject(putObjectRequest); } } } } catch(Exception e) { e.printStackTrace(); }
I need to create my own input stream to get the byte number consumed by Amazon S3. I got this idea from the question here: Upload a file or InputStream to S3 with a progress callback
My code for the ProgressInputStream class is as follows:
package com.spectralnetworks.net.util; import java.io.IOException; import java.io.InputStream; import org.apache.commons.vfs.FileContent; import org.apache.commons.vfs.FileSystemException; public class ProgressInputStream extends InputStream { private final long size; private long progress, lastUpdate = 0; private final InputStream inputStream; private final String name; private boolean closed = false; public ProgressInputStream(String name, InputStream inputStream, long size) { this.size = size; this.inputStream = inputStream; this.name = name; } public ProgressInputStream(String name, FileContent content) throws FileSystemException { this.size = content.getSize(); this.name = name; this.inputStream = content.getInputStream(); } @Override public void close() throws IOException { super.close(); if (closed) throw new IOException("already closed"); closed = true; } @Override public int read() throws IOException { int count = inputStream.read(); if (count > 0) progress += count; lastUpdate = maybeUpdateDisplay(name, progress, lastUpdate, size); return count; }@Override public int read(byte[] b, int off, int len) throws IOException { int count = inputStream.read(b, off, len); if (count > 0) progress += count; lastUpdate = maybeUpdateDisplay(name, progress, lastUpdate, size); return count; } static long maybeUpdateDisplay(String name, long progress, long lastUpdate, long size) { System.out.println("name " + name + " progress " + progress + " lastUpdate " + lastUpdate + " " + "sie " + size); return lastUpdate; } }
But this does not work properly. It prints right up to the file size as follows:
name test progress 4096 lastUpdate 0 sie 30489 name test progress 8192 lastUpdate 0 sie 30489 name test progress 12288 lastUpdate 0 sie 30489 name test progress 16384 lastUpdate 0 sie 30489 name test progress 20480 lastUpdate 0 sie 30489 name test progress 24576 lastUpdate 0 sie 30489 name test progress 28672 lastUpdate 0 sie 30489 name test progress 30489 lastUpdate 0 sie 30489 name test progress 30489 lastUpdate 0 sie 30489
And the actual load takes longer (more than 10 times after printing lines).
What should I do to get true download status?