Java tutorial
/* * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package com.photobucket.api.core; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; import java.util.Vector; import org.apache.http.entity.mime.content.InputStreamBody; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @since 4.0 */ public class InputStreamBodyWithProgress extends InputStreamBody implements ObservableUpload { private static final Logger logger = LoggerFactory.getLogger(InputStreamBodyWithProgress.class); protected int mLastProgressUpdate = 0; private int bytesSent; private int size; private Date startTime; public InputStreamBodyWithProgress(final InputStream in, final int size, final String filename) { super(in, filename); this.size = size; } /** * Returns the total number of bytes in this upload. */ public int getTotalBytes() { return size; } /** * Returns the number of bytes transmitted so far. */ public int getBytesSent() { return bytesSent; } /** * Gets the time that the upload first started. It can be used to measure overall throughput. */ public Date getStartTime() { return startTime; } /** * Override getContentLength since we know it's a file and we can get it's total size. * This allows the request to be sent with a Content-Length instead of having to use chunked * encoding which seems to blow up on some phones when they go to sleep. */ @Override public long getContentLength() { return size; } @Override public void writeTo(final OutputStream out) throws IOException { if (out == null) throw new IllegalArgumentException("Output stream may not be null"); bytesSent = 0; int totalRead = 0; startTime = new Date(); float sizeFloat = (float) size; if (logger.isInfoEnabled()) logger.info("Uploading " + getFilename() + ", " + size + " bytes"); try { // Note AV 9/17/10: Used to be 4K, shrinking it to increase the granularity of the bytesSent counter // available in the ObservableUpload interface. If it performs badly, we should increase it again. byte[] tmp = new byte[1024]; int l; while ((l = getInputStream().read(tmp)) != -1) { totalRead += l; if (logger.isDebugEnabled()) logger.debug("Read " + l + " bytes (" + totalRead + "/" + size + ")"); // Write to the output stream out.write(tmp, 0, l); bytesSent += l; if (logger.isDebugEnabled()) logger.debug("Wrote " + l + " bytes (" + bytesSent + "/" + size + ")"); int newPercentComplete = (int) (((float) bytesSent / sizeFloat) * 100f); if (newPercentComplete > mLastProgressUpdate) { if (logger.isInfoEnabled()) logger.info("Firing progress update, now " + newPercentComplete + "% complete"); mLastProgressUpdate = newPercentComplete; FileUploadProgressEvent evt = new FileUploadProgressEvent(this, getFilename(), bytesSent, newPercentComplete); fireFileUploadProgressEvent(evt); } // Slow down for testing /* if (bytesSent < size) { try { Thread.sleep(125L); } catch (InterruptedException ie) { // Ignore } } */ } out.flush(); } catch (IOException ioe) { if (logger.isErrorEnabled()) logger.error("Upload of " + getFilename() + " failed with IOException: " + ioe.getMessage(), ioe); throw ioe; } finally { getInputStream().close(); } if (logger.isInfoEnabled()) logger.info(getFilename() + " uploaded, sent " + bytesSent + " bytes"); } /** * Stores the List of listeners registered for the UploadProgressEvent */ protected Vector<IFileUploadProgressEventListener> listenerList = new Vector<IFileUploadProgressEventListener>(); /** * Add a listener to the <code>FileUploadProgressEvent</code> * * @param listener the <code>IFileUploadProgressEventListner</code> that will be invoked when the event is fired */ public void addFileUploadProgressEventListener(IFileUploadProgressEventListener listener) { listenerList.add(listener); } /** * Remove a listener from the event listeners * * @param listener the <code>IFileUploadProgressEventListner</code> that will be removed */ public void removeFileUploadProgressEventListener(IFileUploadProgressEventListener listener) { listenerList.remove(listener); } /** * Dispatch the event for the list of listeners that have registered * * @param evt the <code>FileUploadProgressEvent</code> that will be dispatched */ private void fireFileUploadProgressEvent(FileUploadProgressEvent evt) { for (IFileUploadProgressEventListener listener : listenerList) { listener.fileUploadProgressUpdate(evt); } } }