1. 程式人生 > >解決下載ftp文件過程中,瀏覽器直接解析文件(txt,png等)的問題

解決下載ftp文件過程中,瀏覽器直接解析文件(txt,png等)的問題

filename map 需要 etc home 3.0.0 var att esp

搭建了一個ftp服務器,供用戶進行上傳下載,在下載過程中發現,一些文件,例如txt,jpg,png,pdf等直接被瀏覽器解析了。在瀏覽器中顯示其內容,沒有下載。

下面通過網上查詢得到一些解決方法:

1:修改ftp目錄下的.htacess文件,這個文件主要做一些類型映射,使各個文件類型映射為 octet-stream 類型,這樣瀏覽器就不能解析了。

但是,我沒有在ftp目錄下發現該文件,通過filezilla連接服務器, filezilla>服務器>強制顯示隱藏文件 ,也沒有發現該文件。聽說該文件是apache獨有的,我用的是vsftpd服務器,不知道是否存在不一致,於是放棄。

2:第二種方法

使用ajax請求,將文件輸出流(OutputStream)作為回調結果返回。

html代碼, 後臺代碼同第4中方法。

<!DOCTYPE html>
<html lang="en">
<head>
    <script type="text/javascript" src="/js/jquery-3.0.0.min.js"></script>
    <meta charset="UTF-8">
    <title>Title</title>

    <script
> function link() { $.ajax({ type: "get", //請求方式 url: "downloadFileByOutputStream", //請求路徑 data: { "filename":homepage.png‘ //請求參數 }, async: true, //異步,(同步已經廢棄,會報錯)。 success:
function (flag) { //請求成功,flag返回數據 if (flag != "") { console.log(flag); //瀏覽器控制臺打印數據 var obj = eval(flag); //對數據進行轉換 localStorage[UsertypeSelect]=JSON.stringify(obj); //將返回的數據存儲到本地。 }; } }); } </script> </head> <body> <a href="javascript:void(0)" onclick="link()">客戶端下載OutputStream</a> //調用上面的函數 </body> </html>

調用之後,發現數據亂碼, eval(flag)對返回數據轉化失敗。

技術分享圖片

3: 使結果作為PrintWriter流作為回調結果,使用隱藏表單提交的方式對流進行回調。結果 txt,doc等字符文件能夠下載,但是圖片等字節文件不能下載。

前端代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="/js/jquery-3.0.0.min.js"></script>
    <script>
    function download(){
    console.log(執行);
        downloadTemplate(/downloadFileByPrintWriter, filename, homepage.png);
    }
    function downloadTemplate(action, type, value){  //action 請求接口,  type : 後臺接口需要的參數名,value 請求的參數值
    console.log(action);         
        var form = document.createElement(form);     //創建表單 
        document.body.appendChild(form);               
        form.style.display = "none";                 
        form.action = action;              //接口
        form.id = download;              //表單id
        form.method = post;              //請求方式

        var newElement = document.createElement("input");     //創建元素,類型為input
        newElement.setAttribute("type","hidden");             //隱藏
        newElement.name = type;                               //元素名為type
        newElement.value = value;                             //元素值 value
        form.appendChild(newElement);                 
        form.submit();                                         //提交
    }
    </script>
</head>
<body>

<span onclick="download()">客戶端下載PrintWriter</span>

</body>
</html>

後臺代碼:

   /**
     * 根據給定的文件名進行下載
     * Description: 從FTP服務器下載文件
     * @param filename 要下載的文件名
     * @return
     */
    @RequestMapping("/downloadFileByPrintWriter")
    @ResponseBody
    public String downloadFileByPrintWriter(HttpServletResponse response, String filename) throws IOException {
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(host, port);
            ftp.login(username, password);// 登錄
            ftp.enterLocalPassiveMode();  //將ftp設置為被動模式。否則不成功。

            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return "ftp無連接";
            }
            ftp.changeWorkingDirectory(publicFilePath);// 轉移到FTP服務器目錄
            logger.debug("遠程路徑" + publicFilePath);
            FTPFile[] fs = ftp.listFiles();
            for (FTPFile ff : fs) {
                logger.debug("遠程文件名" + ff.getName());
                if (ff.getName().equals(filename)) {
                    InputStream in = ftp.retrieveFileStream(ff.getName());     //讀取ftp服務器文件,返回輸入流
                    int len = 0;
                    byte[] buff = new byte[1024];
                    response.reset();                   //重置響應
                    response.setContentType("application/octet-stream");      //設置響應類型為流類型
                    response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");    //文件名
                    InputStreamReader inputStreamReader = new InputStreamReader(in);

                    PrintWriter fw = response.getWriter();            //得到response的字符打印流

                    //創建一個rd的字符留緩沖區,將字符裝載入緩沖區中
                    BufferedReader bf = new BufferedReader(inputStreamReader);
                    char[] chs = new char[1024];
//                    while ((len = bf.read(chs)) != 0) {
//                        logger.debug("向fw寫入");
////                        fw.write(chs, 0, len);
//                    }
                    String str=null;
                    while ((str = bf.readLine()) != null) {
                        fw.write(str);                      //將ftp輸入流寫出到printWriter  
                        fw.flush();
                    }
                    fw.flush();
                    in.close();
                    fw.close();
                    return "成功";
                }
            }
            ftp.logout();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return "下載失敗";
    }

4:將文件作為OutputStream流作為回調結果,使用隱藏表單提交的方式對流進行回調。成功

html代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="/js/jquery-3.0.0.min.js"></script>
    <script>
    function download(){
    console.log(執行);
        downloadTemplate(/downloadFileByOutputStream, filename, homepage.png);
    }
    function downloadTemplate(action, type, value){
    console.log(action);
        var form = document.createElement(form);
        document.body.appendChild(form);
        form.style.display = "none";
        form.action = action;
        form.id = download;
        form.method = post;

        var newElement = document.createElement("input");
        newElement.setAttribute("type","hidden");
        newElement.name = type;
        newElement.value = value;
        form.appendChild(newElement);
        form.submit();
    }
    </script>
</head>
<body>

<span onclick="download()">客戶端下載PrintWriter</span>

</body>
</html>

後臺代碼:

  /**
     * 根據給定的文件名進行下載
     * Description: 從FTP服務器下載文件
     * @param filename 要下載的文件名
     * @return
     */
    @RequestMapping("/downloadFileByOutputStream")
    @ResponseBody
    public String downloadFileByOutputStream(HttpServletResponse response, String filename) throws IOException {
        logger.debug("下載ByOutputStream");
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(host, port);
            // 如果采用默認端口,可以使用ftp.connect(host)的方式直接連接FTP服務器
            ftp.login(username, password);// 登錄
            ftp.enterLocalPassiveMode();  //將ftp設置為被動模式。否則不成功。
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                return "連接失敗";
            }
            ftp.changeWorkingDirectory(publicFilePath);// 轉移到FTP服務器目錄
            logger.debug("遠程路徑" + publicFilePath);
            FTPFile[] fs = ftp.listFiles();
            for (FTPFile ff : fs) {
                logger.debug("遠程文件名" + ff.getName());
                if (ff.getName().equals(filename)) {
                    InputStream in = ftp.retrieveFileStream(ff.getName());
                    logger.debug(in.toString());
                    int len = 0;
                    byte[] buff = new byte[1024*1024];

                    response.reset();
                    response.setContentType("application/octet-stream");
                    //Name the file
                    response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
//                    response.addHeader("Content-Length", out..ToString());
                    OutputStream out=response.getOutputStream();  //響應輸出字節流

//                    OutputStream out = new PipedOutputStream();
                    while((len=in.read(buff))!=-1){
                        logger.debug("以字節流形式寫出OutPutStream");
                        out.write(buff, 0, len);
                        out.flush();
                    }
                    in.close();
                    out.close();
                    return "成功";
                }
            }

            ftp.logout();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return "失敗";
    }

解決下載ftp文件過程中,瀏覽器直接解析文件(txt,png等)的問題