net.ymate.platform.mvc.web.view.impl.BinaryView.java Source code

Java tutorial

Introduction

Here is the source code for net.ymate.platform.mvc.web.view.impl.BinaryView.java

Source

/*
 * Copyright 2007-2107 the original author or authors.
 *
 * Licensed 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.
 */
package net.ymate.platform.mvc.web.view.impl;

import net.ymate.platform.commons.lang.PairObject;
import net.ymate.platform.commons.util.FileUtils;
import net.ymate.platform.mvc.web.context.WebContext;
import net.ymate.platform.mvc.web.view.AbstractWebView;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.Reader;
import java.net.URLEncoder;

/**
 * <p>
 * BinaryView
 * </p>
 * <p>
 * ??
 * </p>
 *
 * @author (suninformation@163.com)
 * @version 0.0.0
 *          <table style="border:1px solid gray;">
 *          <tr>
 *          <th width="100px">?</th><th width="100px"></th><th
 *          width="100px"></th><th width="100px"></th>
 *          </tr>
 *          <!--  Table ?? -->
 *          <tr>
 *          <td>0.0.0</td>
 *          <td></td>
 *          <td></td>
 *          <td>2011-10-23?11:32:55</td>
 *          </tr>
 *          </table>
 */
public class BinaryView extends AbstractWebView {

    protected String fileName;
    protected Object data;

    private long maxLength = -1;

    /**
     * 
     */
    public BinaryView() {
    }

    /**
     * 
     *
     * @param data ?
     */
    public BinaryView(Object data) {
        this.data = data;
    }

    /**
     * 
     *
     * @param inputStream
     * @param maxLength   ??
     */
    public BinaryView(InputStream inputStream, long maxLength) {
        this.data = inputStream;
        if (maxLength > 0) {
            this.maxLength = maxLength;
        }
    }

    /**
     * @param fileName   ??
     * @param attachment ??
     * @return ??fileName?NULL
     * @throws Exception ??
     */
    public static BinaryView loadFromFile(String fileName, boolean attachment) throws Exception {
        File _file = new File(fileName);
        if (_file.exists() && _file.isFile() && _file.canRead()) {
            BinaryView _view = new BinaryView(new FileInputStream(_file));
            _view.setContentType(FileUtils.MIME_TYPE_MAPS.get(FileUtils.getExtName(_file.getPath())));
            if (attachment) {
                _view.setFileName(_file.getName());
            }
            return _view;
        }
        return null;
    }

    /* (non-Javadoc)
     * @see net.ymate.platform.mvc.web.view.AbstractWebView#renderView()
     */
    protected void renderView() throws Exception {
        HttpServletResponse response = WebContext.getResponse();
        HttpServletRequest request = WebContext.getRequest();
        //
        response.setContentType(StringUtils.defaultIfBlank(getContentType(), "application/octet-stream"));
        //
        if (StringUtils.isNotBlank(fileName)) {
            StringBuilder _dispositionSB = new StringBuilder("attachment;filename=");
            if (request.getHeader("User-Agent").toLowerCase().contains("firefox")) {
                _dispositionSB.append(new String(fileName.getBytes("UTF-8"), "ISO8859-1"));
            } else {
                _dispositionSB.append(URLEncoder.encode(fileName, "UTF-8"));
            }
            response.setHeader("Content-Disposition", _dispositionSB.toString());
        }
        //
        if (this.data == null) {
            return;
        }
        // 
        if (this.data instanceof File) {
            // ??
            maxLength = ((File) this.data).length();
            // ?Range??
            PairObject<Long, Long> _rangePO = __doParseRange(maxLength);
            // 
            if (_rangePO != null) {
                __doSetRangeHeader(request, response, _rangePO);
                // ?
                IOUtils.copyLarge(new FileInputStream((File) this.data), response.getOutputStream(),
                        _rangePO.getKey(), _rangePO.getValue());
            } else {
                // 
                response.setContentLength(
                        (int) IOUtils.copyLarge(new FileInputStream((File) this.data), response.getOutputStream()));
            }
        }
        // 
        else if (this.data instanceof byte[]) {
            byte[] _datas = (byte[]) this.data;
            IOUtils.write(_datas, response.getOutputStream());
            response.setContentLength(_datas.length);
        }
        // 
        else if (this.data instanceof char[]) {
            char[] _datas = (char[]) this.data;
            IOUtils.write(_datas, response.getOutputStream());
            response.setContentLength(_datas.length);
        }
        // ?
        else if (this.data instanceof Reader) {
            Reader r = (Reader) this.data;
            IOUtils.copy(r, response.getOutputStream());
        }
        // ?
        else if (this.data instanceof InputStream) {
            PairObject<Long, Long> _rangePO = __doParseRange(maxLength);
            if (_rangePO != null) {
                __doSetRangeHeader(request, response, _rangePO);
                IOUtils.copyLarge((InputStream) this.data, response.getOutputStream(), _rangePO.getKey(),
                        _rangePO.getValue());
            } else {
                response.setContentLength(
                        (int) IOUtils.copyLarge((InputStream) this.data, response.getOutputStream()));
            }
        }
        // 
        else {
            IOUtils.write(String.valueOf(data), response.getOutputStream());
        }
    }

    private void __doSetRangeHeader(HttpServletRequest request, HttpServletResponse response,
            PairObject<Long, Long> range) {
        // none???
        response.setHeader("Accept-Ranges", "bytes");
        // Content-Length: [?] - [?]
        long _totalLength = range.getValue() - range.getKey();
        response.setHeader("Content-Length", _totalLength + "");
        // Content-Range: bytes [?]-[? - 1]/[?]
        response.setHeader("Content-Range",
                "bytes " + range.getKey() + "-" + (range.getValue() - 1) + "/" + maxLength);
        // response.setHeader("Connection", "Close"); //???IE
        // Status: 206
        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
    }

    /**
     * ?Range????
     *
     * @param maxLength ??
     * @return ?null
     */
    private PairObject<Long, Long> __doParseRange(long maxLength) {
        PairObject<Long, Long> _returnValue = null;
        // Range??
        String _rangeStr = WebContext.getRequest().getHeader("Range");
        if (_rangeStr != null && _rangeStr.startsWith("bytes=") && _rangeStr.length() >= 7) {
            _rangeStr = StringUtils.substringAfter(_rangeStr, "bytes=");
            String[] _ranges = StringUtils.split(_rangeStr, ",");
            // ?Range??...
            for (String _range : _ranges) {
                if (StringUtils.isBlank(_range)) {
                    return null;
                }
                try {
                    // bytes=-100
                    if (_range.startsWith("-")) {
                        long _end = Long.parseLong(_range);
                        long _start = maxLength + _end;
                        if (_start < 0) {
                            return null;
                        }
                        _returnValue = new PairObject<Long, Long>(_start, maxLength);
                        break;
                    }
                    // bytes=1024-
                    if (_range.endsWith("-")) {
                        long _start = Long.parseLong(StringUtils.substringBefore(_range, "-"));
                        if (_start < 0) {
                            return null;
                        }
                        _returnValue = new PairObject<Long, Long>(_start, maxLength);
                        break;
                    }
                    // bytes=10-1024
                    if (_range.contains("-")) {
                        String[] _tmp = _range.split("-");
                        long _start = Long.parseLong(_tmp[0]);
                        long _end = Long.parseLong(_tmp[1]);
                        if (_start > _end) {
                            return null;
                        }
                        _returnValue = new PairObject<Long, Long>(_start, _end + 1);
                    }
                } catch (Throwable e) {
                    return null;
                }
            }
        }
        return _returnValue;
    }

    /**
     * @param data the data to set
     */
    public void setData(Object data) {
        this.data = data;
    }

    /**
     * @param fileName the fileName to set
     */
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

}