socket通過http上傳下載

直接上代碼,涉及http消息格式問題參考其他資料

import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by chao.zeng on 2016/5/30.
 */
public class HttpClient {
    private Socket socket;
    private StringBuilder header=new StringBuilder();
    private List<StringBuilder> bodys=new ArrayList<StringBuilder>();
    private List<StringBuilder> bodyHeadersFile=new ArrayList<StringBuilder>();
    private long contentLength=0;
    private String boundary="----WebKitFormBoundaryUalLNdJ5BjmXlLhv";
    public static void  main(String[] args) throws IOException {
        HttpClient client=new HttpClient("localhost",8080);
        Map<String,String> params=new HashMap<String,String>();
        params.put("id","10030");
        params.put("xx","xxoo");
        Map<String,String> files=new HashMap<String,String>();
        files.put("name1","d:\\deerway.zip");
        files.put("name2","d:\\deerway2.zip");
        client.upload("/cloudolp.dc/deviceApi/cameraupload",params,files);

        Map<String,String> params2=new HashMap<String,String>();
        params2.put("id","10030");
        params2.put("name","name1");
        client=new HttpClient("localhost",8080);
        client.download("/cloudolp.dc/deviceApi/cameradownload",params2,"d:\\xx.zip");
    }
    public HttpClient(String host,int port) throws IOException {
        socket=new Socket(host,port);
    }
    private void setHeader(){
        /**
         * 寫入請求行
         * 第一個參數爲方法,POST,GET等
         * 第二個是URL地址
         * 第三個是HTTP版本,有HTTP/1.0,HTTP/1.1,HTTP/2.0,
         */
        header.append("POST /cloudolp.dc/deviceApi/cameraupload HTTP/1.1\r\n");
        /**
         * 寫入請求頭,請求頭和請求體之間需要一行空行分割
         * Host:參數必須要有,不然服務器不接收
         * Content-Type:因爲是上傳文件,此值必須爲multipart/form-data,後面的boundary是各個請求體參數的分割符,詳情參考http規範
         * 每個頭和體之間要有空行分隔'\r\n'
         */
        header.append("Host: localhost:8088\r\n");
        header.append("Connection:Keep-Alive\r\n");
        header.append("Content-Length:"+contentLength+"\r\n");
        header.append("Content-Type:multipart/form-data; boundary="+boundary+"\r\n");
        header.append("\r\n");
    }
    public void upload(String url,Map<String,String> params,Map<String,String> files) throws IOException {
        /**
         * 計算消息體長度,因爲消息頭需要傳Content-Length,即消息體長度
         * 因爲是multipart/form-data,所以消息體會包含很多部分,每部分用分割符boundary分開(其實是兩個'-'加上頭上定義的分隔符)
         */
        /**
         * 普通參數
         */
        for(Map.Entry<String,String> entry:params.entrySet()){
            StringBuilder body=new StringBuilder();
            body.append("--"+boundary+"\r\n");
            body.append("Content-Disposition: form-data; name=\""+entry.getKey()+"\"\r\n");
            body.append("\r\n");
            body.append(entry.getValue());
            body.append("\r\n");
            bodys.add(body);
            contentLength+=body.toString().getBytes().length;
        }
        /**
         * 文件參數
         */
        for(Map.Entry<String,String> entry:files.entrySet()){
            StringBuilder bodyheader=new StringBuilder();
            bodyheader.append("--"+boundary+"\r\n");
            bodyheader.append("Content-Disposition: form-data; name=\""+entry.getKey()+"\"; filename=\""+entry.getValue()+"\"\r\n");
            bodyheader.append("\r\n");
            bodyHeadersFile.add(bodyheader);
            contentLength+=bodyheader.toString().getBytes().length;
            File file=new File(entry.getValue());
            contentLength+=file.length()+2;
        }
        StringBuilder endboundary=new StringBuilder();
        endboundary.append("--");
        endboundary.append(boundary);
        endboundary.append("--"+"\r\n");

        contentLength+=endboundary.toString().getBytes().length;
        setHeader();
        OutputStream out=socket.getOutputStream();
        out.write(header.toString().getBytes());

        for(StringBuilder body:bodys){
            out.write(body.toString().getBytes());
        }
        int i=0;
        for(Map.Entry<String,String> entry:files.entrySet()){
            out.write(bodyHeadersFile.get(i++).toString().getBytes());//寫入文件頭
            File file=new File(entry.getValue());
            //寫入文件
            InputStream input=new FileInputStream(file);
            byte[] bs=new byte[8192];
            int length=input.read(bs);
            while(length!=-1){
                out.write(bs,0,length);
                length=input.read(bs);
            }
            out.write("\r\n".getBytes());//寫入空行
        }
        //寫入結束標誌
        out.write(endboundary.toString().getBytes());

    }

    public void download(String url,Map<String,String> params,String dest) throws IOException {
        StringBuilder urlsb=new  StringBuilder();
        urlsb.append(url);
        urlsb.append("?");
        for(Map.Entry<String,String> entry:params.entrySet()){
            urlsb.append(entry.getKey());
            urlsb.append("=");
            urlsb.append(entry.getValue());
            urlsb.append("&");
        }
        urlsb.deleteCharAt(urlsb.length()-1);
        StringBuilder sb=new StringBuilder();
        sb.append("GET "+urlsb.toString()+" HTTP/1.1\r\n");
        sb.append("Host: localhost:8088\r\n");
        sb.append("Connection:Keep-Alive\r\n");
        sb.append("\r\n");
        socket.getOutputStream().write(sb.toString().getBytes());
        InputStream input=socket.getInputStream();
        String line=readLine(input);
        //第一行爲響應行,包含狀態碼
        String[] reslines=line.split(" ");
        if(!reslines[1].equals("200")){
            System.out.println("響應出錯:狀態碼爲"+reslines[1]);
            return;
        }
        while(!line.equals("")){
            System.out.println(line);
            line=readLine(input);
        }
        OutputStream out=new FileOutputStream(dest);
        int length=Integer.parseInt(readLine(input),16);
        while(length!=0){
            byte[] content=new byte[length];
            input.read(content);
            out.write(content,0,length);
            input.read();//讀入'\r'
            input.read();//讀入'\n'
            length=Integer.parseInt(readLine(input),16);
        }
    }
    private String readLine(InputStream input) throws IOException {
        StringBuilder sb=new StringBuilder();
        char c=(char)input.read();
        while(c!='\r'){
            sb.append(c);
            c=(char)input.read();
        }
        input.read();
        return sb.toString();
    }
}


發佈了31 篇原創文章 · 獲贊 7 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章