All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.schoolwow.quickhttp.response.ResponseImpl Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
package cn.schoolwow.quickhttp.response;

import cn.schoolwow.quickhttp.document.Document;
import cn.schoolwow.quickhttp.document.DocumentParser;
import cn.schoolwow.quickhttp.domain.ClientConfig;
import cn.schoolwow.quickhttp.domain.RequestMeta;
import cn.schoolwow.quickhttp.domain.ResponseMeta;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpCookie;
import java.net.SocketTimeoutException;
import java.net.URLDecoder;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ResponseImpl implements Response {
    private Logger logger = LoggerFactory.getLogger(ResponseImpl.class);
    private RequestMeta requestMeta;
    private ResponseMeta responseMeta;
    private ClientConfig clientConfig;

    public ResponseImpl(RequestMeta requestMeta, ResponseMeta responseMeta, ClientConfig clientConfig) {
        this.requestMeta = requestMeta;
        this.responseMeta = responseMeta;
        this.clientConfig = clientConfig;
    }

    @Override
    public String url() {
        return responseMeta.httpURLConnection.getURL().toString();
    }

    @Override
    public int statusCode() {
        return responseMeta.statusCode;
    }

    @Override
    public String statusMessage() {
        return responseMeta.statusMessage;
    }

    @Override
    public String charset() {
        return responseMeta.charset;
    }

    @Override
    public String contentType() {
        return responseMeta.httpURLConnection.getContentType();
    }

    @Override
    public long contentLength() {
        return responseMeta.httpURLConnection.getContentLengthLong();
    }

    @Override
    public String filename() {
        String contentDisposition = responseMeta.httpURLConnection.getHeaderField("Content-Disposition");
        if (null == contentDisposition) {
            return null;
        }
        String fileName = null;
        if (contentDisposition.indexOf("filename*=") > 0) {
            fileName = contentDisposition.substring(contentDisposition.indexOf("filename*=") + "filename*=".length());
            String charset = fileName.substring(0, fileName.indexOf("''")).replace("\"", "");
            fileName = fileName.substring(fileName.indexOf("''") + 2).replace("\"", "");
            fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), Charset.forName(charset));
            try {
                fileName = URLDecoder.decode(fileName,charset);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        } else if (contentDisposition.indexOf("filename=") > 0) {
            fileName = contentDisposition.substring(contentDisposition.indexOf("filename=") + "filename=".length());
            fileName = fileName.replace("\"", "").trim();
        }
        return fileName;
    }

    @Override
    public boolean acceptRanges() {
        return hasHeader("Accept-Ranges", "bytes");
    }

    @Override
    public String contentEncoding() {
        List values = header("Content-Encoding");
        return null==values?null:values.get(0);
    }

    @Override
    public boolean hasHeader(String name) {
        return responseMeta.headerMap.containsKey(name);
    }

    @Override
    public boolean hasHeader(String name, String value) {
        return hasHeader(name) && responseMeta.headerMap.get(name).get(0).equals(value);
    }

    @Override
    public List header(String name) {
        return responseMeta.headerMap.get(name);
    }

    @Override
    public Map> headers() {
        return responseMeta.headerMap;
    }

    @Override
    public boolean hasCookie(String name) {
        return clientConfig.cookieOption.hasCookie(responseMeta.topHost,name);
    }

    @Override
    public boolean hasCookie(String name, String value) {
        HttpCookie httpCookie = clientConfig.cookieOption.getCookie(responseMeta.topHost,name);
        return null!=httpCookie&&httpCookie.getValue().equals(value);
    }

    @Override
    public Response maxDownloadSpeed(int maxDownloadSpeed) {
        SpeedLimitInputStream speedLimitInputStream = (SpeedLimitInputStream) responseMeta.inputStream;
        speedLimitInputStream.setMaxDownloadSpeed(maxDownloadSpeed);
        return this;
    }

    @Override
    public String body() throws IOException {
        if (null == responseMeta.body) {
            bodyAsBytes();
        }
        return new String(responseMeta.body,Charset.forName(responseMeta.charset));
    }

    @Override
    public JSONObject bodyAsJSONObject() throws IOException {
        JSONObject object = JSON.parseObject(body());
        return object;
    }

    @Override
    public JSONArray bodyAsJSONArray() throws IOException {
        JSONArray array = JSON.parseArray(body());
        return array;
    }

    @Override
    public JSONObject jsonpAsJSONObject() throws IOException {
        String body = body();
        int startIndex = body.indexOf("(") + 1, endIndex = body.lastIndexOf(")");
        return JSON.parseObject(body.substring(startIndex, endIndex));
    }

    @Override
    public JSONArray jsonpAsJSONArray() throws IOException {
        String body = body();
        int startIndex = body.indexOf("(") + 1, endIndex = body.lastIndexOf(")");
        return JSON.parseArray(body.substring(startIndex, endIndex));
    }

    @Override
    public byte[] bodyAsBytes() throws IOException {
        Path path = Files.createTempFile("QuickHttp", ".response");
        try {
            bodyAsFile(path);
            if(Files.exists(path)){
                responseMeta.body = Files.readAllBytes(path);
            }
        }catch (IOException e){
            throw e;
        }finally {
            Files.deleteIfExists(path);
            disconnect();
        }
        return responseMeta.body;
    }

    @Override
    public void bodyAsFile(String filePath) throws IOException {
        Path path = Paths.get(filePath);
        bodyAsFile(path);
    }

    @Override
    public void bodyAsFile(Path file) throws IOException {
        if (null == responseMeta.inputStream) {
            logger.warn("[写入文件失败]输入流为空!url:{}", url());
            return;
        }

        if (!Files.exists(file.getParent())) {
            Files.createDirectories(file.getParent());
        }

        long fileSize = Files.exists(file) ? Files.size(file) : 0;
        if (null != responseMeta.body) {
            if (Files.exists(file)) {
                Files.write(file, responseMeta.body, StandardOpenOption.APPEND);
            } else {
                Files.write(file, responseMeta.body, StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
            }
        } else {
            //处理超时异常,尝试重试
            int retryTimes = 1;
            while (retryTimes <= requestMeta.retryTimes) {
                try {
                    if (null != responseMeta.httpURLConnection.getContentEncoding() || contentLength() == -1) {
                        Files.copy(responseMeta.inputStream, file, StandardCopyOption.REPLACE_EXISTING);
                    } else {
                        ReadableByteChannel readableByteChannel = Channels.newChannel(responseMeta.inputStream);
                        Set openOptions = null;
                        if (Files.exists(file)) {
                            openOptions = EnumSet.of(StandardOpenOption.APPEND);
                        } else {
                            openOptions = EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
                        }
                        FileChannel fileChannel = FileChannel.open(file, openOptions);
                        fileChannel.transferFrom(readableByteChannel, Files.size(file), contentLength());
                        fileChannel.close();
                    }
                    break;
                } catch (SocketTimeoutException e) {
                    logger.warn("[下载超时]重试{}/{},原因:{},链接:{}", retryTimes, requestMeta.retryTimes, e.getMessage(), url());
                    retryTimes++;
                }
            }
        }
        if (contentLength() > 0) {
            //检查是否下载成功
            long expectFileSize = fileSize + contentLength();
            if (!responseMeta.headerMap.containsKey("Content-Encoding")&&(Files.notExists(file) || Files.size(file) != expectFileSize)) {
                logger.warn("[文件下载失败]预期大小:{},实际大小:{},路径:{}", expectFileSize, Files.size(file), file);
            }else{
                responseMeta.body = Files.readAllBytes(file);
            }
        }
    }

    @Override
    public InputStream bodyStream() {
        return responseMeta.inputStream;
    }

    @Override
    public Document parse() throws IOException {
        if (responseMeta.document == null) {
            if (responseMeta.body == null) {
                body();
            }
            responseMeta.document = Document.parse(body());
        }
        return responseMeta.document;
    }

    @Override
    public DocumentParser parser() throws IOException {
        if (responseMeta.documentParser == null) {
            if (responseMeta.body == null) {
                body();
            }
            responseMeta.documentParser = DocumentParser.parse(body());
        }
        return responseMeta.documentParser;
    }

    @Override
    public void disconnect() {
        try {
            if (null != responseMeta.inputStream) {
                responseMeta.inputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        responseMeta.httpURLConnection.disconnect();
    }

    @Override
    public ResponseMeta responseMeta() {
        return responseMeta;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy