• 文件上传与下载的前后端处理


    这两天在搞一个东西,单据帮助内容的导入导出。具体说就是将单据的帮助信息(字段名称和帮助内容)编辑成Excel,然后上传。后端解析流,使用poi解析Excel内容并保存到数据库中。这就是导入;从数据库读取内容并装入poi里,写入输出流让前端浏览器下载,这就是导出。

    就是这么简单的功能,但我却搞了两天,上传的时候request并不是类型,下载的时候已经写入response的输出流了,但浏览器就是没有弹出下载框。在网上看了个遍都不知道为什么。

    后来终于知道原因了,是因为我用了Ajax向服务端发送请求。Ajax只能传递xml或json(好像有4种,网上的说法感觉都不靠谱,找时间看一看Ajax权威指南这一类的书籍,一次过彻底弄明白吧),而文件的上传下载是涉及到二进制数据的,所以Ajax做不到,只能用form请求。

    上传大概是这么处理:

    // 创建上传文件form
            var form = $("<form>"),   //定义一个form表单
                resFrame = $('<iframe name="res" style="display:none;"></iframe>'),
                fileInput;
            form.attr('id', uploadFormId);
            form.attr('name', uploadFormId);
            form.attr('enctype','multipart/form-data');   //在form表单中添加查询参数
            form.attr('method','post');
            form.attr('action',"");
            form.append(resFrame);
            form.attr('target','res');
            //文件浏览选择控件
            fileInput = $('<input>'); 
            fileInput.attr('id','uploadFile'); 
            fileInput.attr('type','file'); 
            fileInput.attr('name', "file[]"); 
            form.append(fileInput);

    重点是设置好enctype属性和file类型的input元素。再弄一个隐藏的iframe作为form的target,好让提交form请求后页面不会刷新(伪Ajax)

    public String importAction(HttpServletRequest request,HttpServletResponse response, ModelMap modelMap) throws WafException,WafBizException{
            Context ctx = WafContext.getInstance().getContext();
            MultipartHttpServletRequest mReq = (MultipartHttpServletRequest)request;
            MultipartFile mf = mReq.getFile("file[]");
    // ..............
    }

    这样子提交请求,服务端拿到的request就是MultipartHttpServletRequest,用它才可以拿到上传的文件流。

    private Workbook getWb(MultipartFile mf) throws BOSException
        {
    //        MultipartHttpServletRequest
            Workbook wb = null;
            try{
                String name = mf.getOriginalFilename();
                InputStream inputStream = mf.getInputStream();
                String postfix = name.substring(name.lastIndexOf(".") + 1);
                if("xls".equals(postfix)){
                    POIFSFileSystem fs = null;
                    fs = openWorkbookFile(inputStream);
                    wb = new HSSFWorkbook(fs);
                }else if("xlsx".equals(postfix)){
                    wb = new XSSFWorkbook(inputStream);
                }else{
                    throw new BOSException("引入的不是以xls或xlsx为后缀的文件");
                }
            }catch(IOException e){
                throw new BOSException(e);
            }
            return wb;
        }
    View Code

    获取Workbook,用它来处理Excel的方式网上搜一大把

    createDownloadForm = function(){
            // 创建下载文件隐藏form
            var form = $("<form>"),   //定义一个form表单
                resFrame = $('<iframe name="res" style="display:none;"></iframe>');
            form.attr('id', downloadFormId);
            form.attr('style','display:none');   //在form表单中添加查询参数
            form.attr('method','post');
            form.attr('action',"");
            form.append(resFrame);
            form.attr('target','res');
            downloadForm = form;
            return form;
        }
    View Code

    下载也使用form提交请求,使用Ajax无效,Ajax返回的responseText是一堆看不懂的乱码,当然浏览器不会自动下载文件。

    if(isDownload)
                form.submit();
            else{
                waf.block.show({
                    text: '正在导入,请稍后...'
                })
                form.ajaxSubmit({
                    url: "?method="+action,
                    type: "post",
                    async: false,
                    //dataType:"json",
                    success: function(data){
                        waf.block.hide();
                        if("success" == data.result){
                            waf.msgBox.showInfo("导入成功");
                        }else{
                            waf.msgBox.showInfo(data.summany);
                        }
                    },
                    error: function(data){
                        waf.block.hide();
                        waf.msgBox.showInfo("导入失败");
                    }
                });
            }
    View Code

    还有很奇怪的一点,如果是下载,一定要用调用form.submit提交,用下面的AjaxSubmit提交浏览器也不会自动下载文件。上传文件应该两种方式都可以,但AjaxSubmit可以添加返回处理函数。

    // 文件名称
                String fileName = billTypeEnum.getAlias() + "-帮助内容.xlsx";
                
                // 导出,让前台浏览器自动下载
                String headerStr="attachment;filename=" + new String(fileName.getBytes("utf-8"),"ISO8859-1");
                response.setContentType(FileUploadUtils.getContentType("xlsx"));
                response.setHeader("Content-disposition",headerStr);
                ServletOutputStream output = null;
                
                output = response.getOutputStream();
                wb.write(output);
                output.flush();
                output.close();
    View Code

    后端大概这么处理。fileName是下载时的默认文件名。FileUploadUtils.getContentType("xlsx")返回的是"application/x-excel"。

    以上代码片段,前端使用jQuery,后端使用java servlet

  • 相关阅读:
    Mysql安装
    Python的内存管理机制
    Ansible模块
    Redis持久化
    Linux——ansible(1)
    Flask
    Flask入门
    ajax处理回调函数,用ajax向后台发送数据
    数字类型钱币转换为大写
    ligerui多选动态下拉框
  • 原文地址:https://www.cnblogs.com/var-iable/p/3681702.html
Copyright © 2020-2023  润新知