前后台交互實現點擊超鏈接通過指定的 url 去網絡或者文件服務器下載文件


前台 VUE 界面:

<el-table-column prop="attachment" align="center" label="附件詳情">
    <template slot-scope="scope">
        <!--<el-button @click="downloadFile(scope.row.fileName,scope.row.fileUrl)">{{scope.row.fileName}}</el-button>-->
        <a @click="downloadFile(scope.row.fileName,scope.row.fileUrl)">{{scope.row.fileName}}</a>
    </template>
</el-table-column>
//window.open打開一個新的瀏覽器窗口,通過 url 對后台的 rest 接口進行調用
downloadFile(fileName,fileUrl){ let param
= {"fileUrl": fileUrl, "fileName": fileName};   window.open(   downloadManage.downloadFile(param),   this.openType ); },
/* 下載文件,對參數 url 和 fileName 進行拼接處理,然后通過 window.open 對后台的 rest 接口進行調用 */
export const downloadManage = {
  downloadFile: (query) => requestGetUrl('/process/downloadFile.do_', query, 'post'),
};

 

后台java代碼:(rest接口,供前台進行調用)

  /**
     * 下載文件   
     *
     * @return
     */
    @RequestMapping("/downloadFile.do_")
    @ResponseBody
    public void downloadFile(
            HttpServletResponse response,
            @RequestParam String fileUrl,
            @RequestParam String fileName
    ) {
        downLoadFromUrl(fileUrl,fileName,response);
    }

    /**
     * 從網絡Url中下載文件
     * @param urlStr       指定的url
     * @param fileName     下載文件完成要叫的名字
     * @param response
     */
    public static void  downLoadFromUrl(String urlStr,String fileName,HttpServletResponse response){

        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
    
         //增加頭部,說明該文件為附件,只能進行下載,不直接讀
            response.setContentType("application/x-msdownload; charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

            //得到輸入流
            InputStream inputStream = conn.getInputStream();

            BufferedInputStream bis = new BufferedInputStream(inputStream);
            OutputStream os = response.getOutputStream();
            BufferedOutputStream bos = new BufferedOutputStream(os);
            /* ContentLength必須設置,否則文件下載不全
             * 或者調用 BufferedOutputStream#write(byte[] b, int off, int len) 方法輸出
             */
            response.setContentLength(bis.available());
            byte[] b = new byte[1024];
            while(bis.read(b) != -1) {
                bos.write(b);
            }
            bos.flush();


            LOGGER.info("info:"+fileName+" download success");
        } catch (IOException e) {
            LOGGER.error("uploadFile failed", e);
        }

    }

注意:上面的方法有一個小問題:用過url去網絡獲取 inputStream 是一點一點不斷獲取,獲取的過程中就去寫這個 inputStream  ,則 inputStream  還沒有獲取完就寫了,導致文件最后有缺失,所以可以給 inputStream 加一個同步鎖synchronized,就能使 inputStream  全部獲取完並寫,這樣就能獲取完整的 inputStream 並寫下來,就能下載一個完整的文件

public static void  downLoadFromUrl(String urlStr,String fileName,HttpServletResponse response){

        URL url = null;
        HttpURLConnection conn = null;
        try {
            url = new URL(urlStr);
            conn = (HttpURLConnection)url.openConnection();
        }catch (Exception e) {
            LOGGER.error("HttpURLConnection failed", e);
        }
        try (
                InputStream inputStream = conn.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(inputStream);
                OutputStream os = response.getOutputStream();
                BufferedOutputStream bos = new BufferedOutputStream(os);
        ) {
            //未知上傳的文件類型設置ContentType 和 Header
            response.setContentType("application/octet-stream; charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + new String(fileName.getBytes(),"ISO8859-1"));

            //同步塊,同步 inputStream ,邊獲取 inputStream 邊寫,一直到全部獲取完 inputStream
            synchronized (inputStream) {
                byte[] b = new byte[1024];
                int count = 0;
                int len;
                while((len = bis.read(b)) != -1) {
                    bos.write(b, 0, len);
                    count++;
                }
                bos.flush();
                //多少 Kb 大小的文件,則循環多少次,為count值
                LOGGER.info("write BufferedOutputStream:" + count);
                LOGGER.info("info:" + fileName + " download success");
            }
        } catch (Exception e) {
            LOGGER.error("uploadFile failed", e);
        }

    }

 

會出現如下通常我們網上點擊某超鏈接下載文件的效果:(下載完成出現在瀏覽器頁面左下角)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM