From dfa61c3058da141af351b7f34efdd03d00d581a3 Mon Sep 17 00:00:00 2001 From: adiaholic Date: Wed, 8 May 2019 19:28:13 +0530 Subject: [PATCH] Extend `HttpFileUploadManager` with InputStream parameter Add support for InputStreams as Android is tending towards inputStreams over file uploads. Solves SMACK-867 --- .../httpfileupload/HttpFileUploadManager.java | 64 +++++++++++++++---- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadManager.java b/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadManager.java index 931068799..ea367e9f4 100644 --- a/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadManager.java +++ b/smack-experimental/src/main/java/org/jivesoftware/smackx/httpfileupload/HttpFileUploadManager.java @@ -21,12 +21,14 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.WeakHashMap; import java.util.logging.Level; import java.util.logging.Logger; @@ -43,7 +45,7 @@ import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnectionRegistry; import org.jivesoftware.smack.XMPPException; - +import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.packet.DiscoverInfo; import org.jivesoftware.smackx.httpfileupload.UploadService.Version; @@ -245,7 +247,7 @@ public final class HttpFileUploadManager extends Manager { * Note that this is a synchronous call -- Smack must wait for the server response. * * @param file file to be uploaded - * @param listener upload progress listener of null + * @param listener Upload progress listener or null * @return public URL for sharing uploaded file * * @throws InterruptedException if the calling thread was interrupted. @@ -259,12 +261,56 @@ public final class HttpFileUploadManager extends Manager { throw new FileNotFoundException("The path " + file.getAbsolutePath() + " is not a file"); } final Slot slot = requestSlot(file.getName(), file.length(), "application/octet-stream"); - - uploadFile(file, slot, listener); - + final long fileSize = file.length(); + // Construct the FileInputStream first to make sure we can actually read the file. + final FileInputStream fis = new FileInputStream(file); + upload(listener, fileSize, fis, slot); return slot.getGetUrl(); } + /** + * Request slot and uploaded stream to HTTP upload service. + * + * You don't need to request slot and upload input stream separately, this method will do both. + * Note that this is a synchronous call -- Smack must wait for the server response. + * + * @param inputStream Input stream used for the upload. + * @param fileName Name of the file. + * @param fileSize Size of the file. + * @return public URL for sharing uploaded file + * @throws XMPPErrorException XMPPErrorException if there was an XMPP error returned. + * @throws InterruptedException If the calling thread was interrupted. + * @throws SmackException If Smack detected an exceptional situation. + * @throws IOException If an I/O error occurred. + */ + public URL uploadFile(InputStream inputStream, String fileName, long fileSize) throws XMPPErrorException, InterruptedException, SmackException, IOException { + return uploadFile(inputStream, fileName, fileSize, null); + } + + /** + * Request slot and uploaded stream to HTTP upload service. + * + * You don't need to request slot and upload input stream separately, this method will do both. + * Note that this is a synchronous call -- Smack must wait for the server response. + * + * @param inputStream Input stream used for the upload. + * @param fileName Name of the file. + * @param fileSize file size in bytes. + * @param listener upload progress listener or null. + * @return public URL for sharing uploaded file + * @throws XMPPErrorException XMPPErrorException if there was an XMPP error returned. + * @throws InterruptedException If the calling thread was interrupted. + * @throws SmackException If Smack detected an exceptional situation. + * @throws IOException If an I/O error occurred. + */ + public URL uploadFile(InputStream inputStream, String fileName, long fileSize, UploadProgressListener listener) throws XMPPErrorException, InterruptedException, SmackException, IOException { + Objects.requireNonNull(inputStream, "Input Stream cannot be null"); + Objects.requireNonNull(fileName, "Filename Stream cannot be null"); + Objects.requireNonNull(fileSize, "Filesize Stream cannot be null"); + final Slot slot = requestSlot(fileName, fileSize, "application/octet-stream"); + upload(listener, fileSize, inputStream, slot); + return slot.getGetUrl(); + } /** * Request a new upload slot from default upload service (if discovered). When you get slot you should upload file @@ -385,11 +431,7 @@ public final class HttpFileUploadManager extends Manager { setTlsContext(sslContext); } - private void uploadFile(final File file, final Slot slot, UploadProgressListener listener) throws IOException { - final long fileSize = file.length(); - - // Construct the FileInputStream first to make sure we can actually read the file. - final FileInputStream fis = new FileInputStream(file); + private void upload(UploadProgressListener listener, long fileSize, InputStream iStream, Slot slot) throws IOException { final URL putUrl = slot.getPutUrl(); @@ -419,7 +461,7 @@ public final class HttpFileUploadManager extends Manager { listener.onUploadProgress(0, fileSize); } - BufferedInputStream inputStream = new BufferedInputStream(fis); + BufferedInputStream inputStream = new BufferedInputStream(iStream); // TODO Factor in extra static method (and re-use e.g. in bytestream code). byte[] buffer = new byte[4096];