• 前后台交互实现点击超链接通过指定的 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);
            }
    
        }

    会出现如下通常我们网上点击某超链接下载文件的效果:(下载完成出现在浏览器页面左下角)

  • 相关阅读:
    vs2005 配置winpcap
    qt 解决中文乱码问题
    [翻译] QT正则表达式
    使用QSetting 读写ini文件
    [转]GNOME快捷键
    华为面试题之大整数相加
    qt 程序windows 上发布
    win7英文版中文乱码问题
    CURL命令 Alex
    Sendfile机制 Alex
  • 原文地址:https://www.cnblogs.com/liuqing576598117/p/9936400.html
Copyright © 2020-2023  润新知