Java tutorial
/* Copyright c 2005-2012. * Licensed under GNU LESSER General Public License, Version 3. * http://www.gnu.org/licenses */ package org.beangle.web.io; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.StopWatch; import org.beangle.web.mime.MimeTypeProvider; /** * SplitStreamDownloader * <p> * Split download senario like this: * <li>Server first response:200</li> * * <pre> * Content-Length=106786028 * Accept-Ranges=bytes * </pre> * * <li>Client send request :</li> * * <pre> * Range: bytes=2000070-106786027 * </pre> * * <li>Server send next response:206</li> * * <pre> * Content-Length=106786028 * Content-Range=bytes 2000070-106786027/106786028 * </pre> * * @author chaostone */ public class SplitStreamDownloader extends DefaultStreamDownloader { public SplitStreamDownloader() { super(); } public SplitStreamDownloader(MimeTypeProvider mimeTypeProvider) { super(mimeTypeProvider); } @Override public void download(HttpServletRequest request, HttpServletResponse response, InputStream input, String name, String display) { String attach = getAttachName(name, display); response.reset(); addContent(request, response, attach); response.setHeader("Accept-Ranges", "bytes"); response.setHeader("connection", "Keep-Alive"); int length = 0; long start = 0L; long begin = 0L; long stop = 0L; StopWatch watch = new StopWatch(); watch.start(); try { length = input.available(); stop = length - 1; response.setContentLength(length); String rangestr = request.getHeader("Range"); if (null != rangestr) { String[] readlength = StringUtils.substringAfter(rangestr, "bytes=").split("-"); start = Long.parseLong(readlength[0]); if (readlength.length > 1 && StringUtils.isNotEmpty(readlength[1])) { stop = Long.parseLong(readlength[1]); } if (start != 0) { response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); String crange = "bytes " + start + "-" + stop + "/" + length; response.setHeader("Content-Range", crange); } } OutputStream output = response.getOutputStream(); input.skip(start); begin = start; int size = 4 * 1024; byte[] buffer = new byte[size]; for (int step = maxStep(start, stop, size); step > 0; step = maxStep(start, stop, size)) { int readed = input.read(buffer, 0, step); if (readed == -1) break; output.write(buffer, 0, readed); start += readed; } } catch (IOException e) { } catch (Exception e) { logger.warn("download file error " + attach, e); } finally { IOUtils.closeQuietly(input); if (logger.isDebugEnabled()) { String percent = null; if (length == 0) { percent = "100%"; } else { percent = ((int) (((start - begin) * 1.0 / length) * 10000)) / 100.0f + "%"; } long time = watch.getTime(); int rate = 0; if (start - begin > 0) { rate = (int) (((start - begin) * 1.0 / time * 1000) / 1024); } logger.debug("{}({}-{}/{}) download {}[{}] in {} ms with {} KB/s", array(attach, begin, stop, length, start - begin, percent, time, rate)); } } } private Object[] array(Object... objects) { return objects; } public int maxStep(long start, long stop, int bufferSize) { if (stop - start + 1 >= bufferSize) { return bufferSize; } else { return (int) (stop - start + 1); } } }