通過Java WebService介面從服務端下載檔案

來源:互聯網
上載者:User

標籤:下載   java   webservice   

一、 前言

本文講述如何通過webservice介面,從服務端下載檔案、報告到用戶端。適用於跨系統間的檔案互動,傳輸檔案不大的情況(控制在幾百M以內)。對於這種情況搭建一個FTP環境,增加了系統部署的複雜度和系統對外暴露的介面。通過在服務端讀取檔案,返回位元組流到用戶端的方式比較簡單。
下面採用restful的介面形式,滿足SOA架構介面要求。如下代碼拷貝到eclipse中即可運行,功能自測試回合正常。範例代碼的服務端和用戶端在同一台PC上運行,放到不同PC上運行改一下發布服務和請求服務的IP地址。

二、 環境準備

2.1 CXF組件:Java端用於發布WebService服務的開源組件,內部內建jetty Web容器。百度官網下載。
2.2 Eclipse:Java開發IDE。

三、 檔案下載服務端開發3.1 建立服務端Java項目,匯入CXF lib目錄下的Jar包。3.2 定義restful的WebService介面,用於下載檔案。
/** * 下載報告檔案WebService介面, 對於大於20M的檔案分多次傳輸。這裡不對檔案先讀取緩衝,再分批返回; * 而是每次重新讀取檔案,目的是為了讓本服務無狀態,能夠通過ngnix反向 Proxy多個執行個體,解決服務的可靠性 * 和負載平衡問題。這樣做有一個風險,在分批傳送過程中,如果檔案被修改或者刪除了將導致檔案讀取失敗。 *  * @author Elon * @version 1.0 2015-06-30 */@Path("/DownloadFileWS")public class DownloadFileWS {           // 單次傳送最大位元組數20M。    private final static int maxsize_once;    static    {        maxsize_once = 1024 * 1024 * 20;    }    /**     * 下載檔案。讀取檔案內容轉換為位元組流,大於10M分多次傳輸。     * @param req 請求參數     * @return 下載響應     */    @POST    @Path("/downloadFile")    public DownloadFileResponseVO downloadFile(DownloadFileRequestVO req){        try {            return readFileByte(req);        } catch (IOException e) {            e.printStackTrace();            DownloadFileResponseVO vo = new DownloadFileResponseVO();            vo.setErrCode(DownloadErrCodeEnum.READ_FILE_EXCEPTION);            return vo;        }    }    /**     * 讀取檔案內容,構建檔案位元組流返回對象。     * @param req 請求參數     * @return 讀取檔案傳回值。     * @throws IOException IO異常     */    private DownloadFileResponseVO readFileByte(DownloadFileRequestVO req) throws IOException {         DownloadFileResponseVO vo = new DownloadFileResponseVO();        // 擷取判斷檔案最近修改時間        File fileObject = new File(req.getFilePath());        final long fileLastModifiedTime = fileObject.lastModified();        // 判斷分批傳過程中檔案是否修改        if (fileLastModifiedTime != req.getFileLastModifiedTime()                && req.getFileLastModifiedTime() != -1)         {               vo.setErrCode(DownloadErrCodeEnum.FILE_HAS_MODIFIED_WHILE_DOWNLOAD);            return vo;        }        // 讀取檔案位元組流。        ByteArrayOutputStream fileStream = new ByteArrayOutputStream(1024);        FileInputStream file = new FileInputStream(req.getFilePath());        byte[] readbuff = new byte[1024];        while(file.read(readbuff) != -1) {            fileStream.write(readbuff);        }        file.close();        // 構建返迴文件位元組資訊。超過20M, 一次只返回20M。        final byte[] fileBuff = fileStream.toByteArray();        int end = 0;        if (fileBuff.length - req.getStart() > maxsize_once) {            end = req.getStart() + maxsize_once;            vo.setEof(false);        } else {                end = fileBuff.length;            vo.setEof(true);        }        // 拷貝[start, end)範圍內的位元組到傳回值中。        vo.setFileByteBuff(Arrays.copyOfRange(fileBuff, req.getStart(), end));        vo.setStart(end);        vo.setErrCode(DownloadErrCodeEnum.DOWN_LOAD_SUCCESS);        vo.setFileLastModifiedTime(fileLastModifiedTime);        fileStream.close();        return vo;    }}
3.3 介面中使用輸入參數、傳回值、錯誤碼定義

3.3.1 輸入參數類型定義

/** * 下載檔案請求參數類型。 *  * @author Elon * @version 1.0 2015-06-30 */@XmlRootElement(name = "DownloadFileRequest")public class DownloadFileRequestVO implements Serializable{    /**     * 序列化編碼     */    private static final long serialVersionUID = 3142085277564296839L;    // 檔案路徑    private String filePath;    // 讀檔案資料起始位置    private int start;    // 第一次讀取檔案時間(用於在分批傳送檔案過程中判斷檔案是否被修改了)    private long fileLastModifiedTime;    DownloadFileRequestVO()     {        setFilePath("");        setStart(0);        setFileLastModifiedTime(-1);    }    public String getFilePath() {        return filePath;    }    public void setFilePath(String filePath) {        this.filePath = filePath;    }    public int getStart() {        return start;    }    public void setStart(int start) {        this.start = start;    }    public long getFileLastModifiedTime() {        return fileLastModifiedTime;    }    public void setFileLastModifiedTime(long fileLastModifiedTime) {        this.fileLastModifiedTime = fileLastModifiedTime;    }    @Override    public String toString() {        return "filePath: " + filePath + "\n"                + "start: " + String.valueOf(start);    }}

3.3.2 傳回值類型定義

/** * 檔案下載介面傳回值類型 *  * @author Elon * @version 1.0 2015-06-30 */@XmlRootElement(name = "FileVO")public class DownloadFileResponseVO implements Serializable{    /**     * 序列化編號     */    private static final long serialVersionUID = -2218217669316014388L;    // 檔案位元組流緩衝    private byte[] fileByteBuff;    // 標識檔案傳輸是否結束    private boolean eof;    // 下一批讀取檔案資料起始位置    private int start;    // 第一次讀取檔案時間(用於在分批傳送檔案過程中判斷檔案是否被修改了)    private long fileLastModifiedTime;    // 錯誤碼    private DownloadErrCodeEnum errCode;    public DownloadFileResponseVO() {        setFileByteBuff(null);        setEof(false);        setStart(0);        setErrCode(DownloadErrCodeEnum.ERR_CODE_NA);        setFileLastModifiedTime(-1);    }    public byte[] getFileByteBuff() {        return fileByteBuff;    }    public void setFileByteBuff(byte[] fileByteBuff) {        this.fileByteBuff = fileByteBuff;    }    public boolean isEof() {        return eof;    }    public void setEof(boolean eof) {        this.eof = eof;    }    public int getStart() {        return start;    }    public void setStart(int start) {        this.start = start;    }    public DownloadErrCodeEnum getErrCode() {        return errCode;    }    public void setErrCode(DownloadErrCodeEnum errCode) {        this.errCode = errCode;    }    public long getFileLastModifiedTime() {        return fileLastModifiedTime;    }    public void setFileLastModifiedTime(long fileLastModifiedTime) {        this.fileLastModifiedTime = fileLastModifiedTime;    }    @Override    public String toString() {        return "fileByteBuff: " + fileByteBuff.toString() + "\n"                + "eof: " + String.valueOf(eof) + "\n"                + "start: " + String.valueOf(start);    }}

3.3.3 錯誤碼枚舉類型定義

/** * 下載檔案錯誤碼 * @author Elon * @version 1.0 2015-06-30 */public enum DownloadErrCodeEnum {    DOWN_LOAD_SUCCESS, // 下載成功    READ_FILE_EXCEPTION, // 讀取檔案異常    FILE_HAS_MODIFIED_WHILE_DOWNLOAD, // 在分批下載檔案的過程中檔案發生了修改    ERR_CODE_NA, // 無效錯誤碼}

3.3.4 發布restful服務

public class StartServer {    public static void main(String[] args)     {        publishWS();    }    private static void publishWS()     {        JAXRSServerFactoryBean bean = new JAXRSServerFactoryBean();        bean.setAddress("http://10.61.67.246:10011/download");        bean.setServiceBean(new DownloadFileWS());        bean.create();        // 阻塞線程、等待外部訊息請求。        while(true)        {            try {                Thread.sleep(5000);            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}
四、 檔案下載用戶端開發4.1 建立用戶端Java項目,匯入CXF lib目錄下的Jar包。4.2 調用介面下載檔案,檔案位元組流寫入目標檔案儲存。
public class StartClient {    public static void main(String[] args) throws IOException     {        downloadFileClient();    }    private static void downloadFileClient() throws IOException     {        DownloadFileRequestVO req = new DownloadFileRequestVO();        req.setFilePath("D:\\TEMP\\測試報告壓縮包檔案.zip");        req.setStart(0);        // 迴圈下載檔案位元組流,直到下載完檔案所有內容。        FileOutputStream out = new FileOutputStream("D://TEMP/123.zip");        while (true)        {               WebClient webClient = WebClient.create("http://10.61.67.246:10011");            webClient.encoding("UTF-8");            Response response = webClient.path("download/DownloadFileWS/downloadFile")                    .post(req);            GenericType<DownloadFileResponseVO> vo = new GenericType<DownloadFileResponseVO>(){};            DownloadFileResponseVO rsp = response.readEntity(vo);            webClient.close();            if (rsp.getErrCode() != DownloadErrCodeEnum.DOWN_LOAD_SUCCESS)            {                System.err.println("Download file err: " + rsp.getErrCode());                break;            }            // 將位元組流寫到檔案            out.write(rsp.getFileByteBuff());            if (rsp.isEof())            {                break;            }            else            {                req.setStart(rsp.getStart());                req.setFileLastModifiedTime(rsp.getFileLastModifiedTime());            }        }        // 輸出、關閉檔案        try         {            out.flush();            out.close();            System.err.println("Download file success!");        }         catch (Exception e)         {            e.printStackTrace();        }    }}

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

通過Java WebService介面從服務端下載檔案

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.