框架 day50 BOS项目 4 批量导入(ocupload插件,pinyin4J)/POI解析Excel/Combobox下拉框/分区组合条件分页查询(ajax)/分区数据导出(Excel)

知识点:

批量导入(ocupload插件,pinyin4J

/POI解析Excel(apache POI)

/区域分页查询

/Combobox下拉框

/分区组合条件分页查询(ajax)

/分区数据导出(Excel下载)


BOS项目笔记第4天





1.    区域批量导入功能


*Ajax不支持文件上传。

*上传并且不刷新上传页面原理:

Target到一个0,0,0的隐藏iframe里,造成一个没有刷新的假象

	

*选择上传文件后自动上传(无上传按钮)原理:

文件输入框onchange事件 内容一变化就自动提交

 

 

1.1   一键上传插件使用

    将js文件复制到项目中

 jquery.ocupload-1.1.2.js

ocupload jquery 的应用代码

    $(function () {  $(".uploadfile").upload({  action: 'CourseXMLFileUploadHander.ashx',  name: 'xml',  params: {  'type': 'uploadCourseXMLFile',  'rand': Math.random()  },  onSelect: function (self, element) {  this.autoSubmit = false;  var re = new RegExp("(xml){1}quot;, "i");  if (!re.test(this.filename())) {  alert("Only xml file can be uploaded");  }  else {  this.submit();  }  },  onSubmit: function (self, element) {  $('.uploadfile').hide();  $('#ajax_update').parent().show();  //alert('Uploading file...');  },  onComplete: function (data, self, element) {  $('#ajax_update').parent().hide();  $('.uploadfile').show();  self.resetInput();  try {  var ret = data;  if (ret.indexOf("exception") >= 0) {  alert('Upload file exception: ' + eval(data)[0].exception);  }  else {  showSuccess('File is successfully Load.');  uploadSuccess(ret);  }  } catch (err) {  alert(data);  }  }  });  });  


    在需要使用一键上传插件的页面引入js文件,提供一个元素,调用插件的upload方法,动态修改html元素

 简单示例


原理:js插件会动态的创建form表单和iframe

 

1.1   在region.jsp页面应用一键上传插件

    引入js文件

    调用插件的upload方法

	$(function(){$("#button-import").upload({action:'${pageContext.request.contextPath}/regionAction_importXls.action',name:'upload',onComplete: function (data, self, element) { if(data == '1'){$.messager.alert("提示信息","导入数据成功!","info");}else{$.messager.alert("提示信息","导入数据失败!","warning");}}});});

1.2   创建RegionAction提供importXls方法

@Controller
@Scope("prototype")
public class RegionAction extends BaseAction {private File upload;// 用于接收上传的文件public void setUpload(File upload) {this.upload = upload;}// 导入区域数据public String importXls() throws FileNotFoundException, IOException {System.out.println(upload);// 加载Excel文件到内存中HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(upload));// 读取第一个Sheet页HSSFSheet sheet = workbook.getSheetAt(0);List list = new ArrayList();for (Row row : sheet) {// int rowNum = row.getRowNum();String value1 = row.getCell(0).getStringCellValue();// idString value2 = row.getCell(1).getStringCellValue();// proviceString value3 = row.getCell(2).getStringCellValue();// cityString value4 = row.getCell(3).getStringCellValue();// districtString value5 = row.getCell(4).getStringCellValue();// postcodeRegion region = new Region(value1, value2, value3, value4, value5);// 简码String shortcode = StringUtils.join(PinYin4jUtils.getHeadByString(value2 + value3), "");// 城市编码String citycode = PinYin4jUtils.hanziToPinyin(value3, "");region.setShortcode(shortcode);region.setCitycode(citycode);list.add(region);}String f = "1";try {regionService.saveBatch(list);} catch (Exception e) {f = "0";}ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");ServletActionContext.getResponse().getWriter().print(f);return NONE;}

配置struts.xml


*重复导入时出现主键冲突:

Duplicate entry ......

解决方法:使用saveOrUpdate


1.3   使用apache POI解析Excel文件


/*** 测试POI解析Excel文件*/
public class POITest {@Testpublic void test1() throws FileNotFoundException, IOException {HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(new File("d:\\abc.xls")));HSSFSheet sheet = workbook.getSheetAt(0);//读取第一个sheet页for (Row row : sheet) {//循环读取每一行String v1 = row.getCell(0).getStringCellValue();//获得当前行的第一个单元格的文字内容String v2 = row.getCell(1).getStringCellValue();String v3 = row.getCell(2).getStringCellValue();String v4 = row.getCell(3).getStringCellValue();String v5 = row.getCell(4).getStringCellValue();System.out.println(v1 + " " + v2 + " "  +v3 + " " + v4 + " " + v5);}}
}


Pinyin4J

 

	@Testpublic void test1() {String city = "北京市";String province = "河北省";String city2 = "石家庄市";String district = "长安区";// 城市编码 北京市-----》beijingString str1 = PinYin4jUtils.hanziToPinyin(city.substring(0, city.length() - 1), "");System.out.println(str1);String info = province.substring(0, province.length() - 1)+ city2.substring(0, city2.length() - 1)+ district.substring(0, district.length() - 1);// 简码河北省石家庄市长安区-----》hbsjzcaString[] strings = PinYin4jUtils.getHeadByString(info);String join = StringUtils.join(strings, "");System.out.println(join);}
}



utils工具类

package cn.itcast.bos.utils;import java.util.Arrays;import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;public class PinYin4jUtils {/*** 将字符串转换成拼音数组* * @param src* @return*/public static String[] stringToPinyin(String src) {return stringToPinyin(src, false, null);}/*** 将字符串转换成拼音数组* * @param src* @return*/public static String[] stringToPinyin(String src, String separator) {return stringToPinyin(src, true, separator);}/*** 将字符串转换成拼音数组* * @param src* @param isPolyphone*            是否查出多音字的所有拼音* @param separator*            多音字拼音之间的分隔符* @return*/public static String[] stringToPinyin(String src, boolean isPolyphone,String separator) {// 判断字符串是否为空if ("".equals(src) || null == src) {return null;}char[] srcChar = src.toCharArray();int srcCount = srcChar.length;String[] srcStr = new String[srcCount];for (int i = 0; i < srcCount; i++) {srcStr[i] = charToPinyin(srcChar[i], isPolyphone, separator);}return srcStr;}/*** 将单个字符转换成拼音* * @param src* @return*/public static String charToPinyin(char src, boolean isPolyphone,String separator) {// 创建汉语拼音处理类HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();// 输出设置,大小写,音标方式defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);StringBuffer tempPinying = new StringBuffer();// 如果是中文if (src > 128) {try {// 转换得出结果String[] strs = PinyinHelper.toHanyuPinyinStringArray(src,defaultFormat);// 是否查出多音字,默认是查出多音字的第一个字符if (isPolyphone && null != separator) {for (int i = 0; i < strs.length; i++) {tempPinying.append(strs[i]);if (strs.length != (i + 1)) {// 多音字之间用特殊符号间隔起来tempPinying.append(separator);}}} else {tempPinying.append(strs[0]);}} catch (BadHanyuPinyinOutputFormatCombination e) {e.printStackTrace();}} else {tempPinying.append(src);}return tempPinying.toString();}public static String hanziToPinyin(String hanzi) {return hanziToPinyin(hanzi, " ");}/*** 将汉字转换成拼音* * @param hanzi* @param separator* @return*/public static String hanziToPinyin(String hanzi, String separator) {// 创建汉语拼音处理类HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();// 输出设置,大小写,音标方式defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);String pinyingStr = "";try {pinyingStr = PinyinHelper.toHanyuPinyinString(hanzi, defaultFormat,separator);} catch (BadHanyuPinyinOutputFormatCombination e) {// TODO Auto-generated catch blocke.printStackTrace();}return pinyingStr;}/*** 将字符串数组转换成字符串* * @param str* @param separator*            各个字符串之间的分隔符* @return*/public static String stringArrayToString(String[] str, String separator) {StringBuffer sb = new StringBuffer();for (int i = 0; i < str.length; i++) {sb.append(str[i]);if (str.length != (i + 1)) {sb.append(separator);}}return sb.toString();}/*** 简单的将各个字符数组之间连接起来* * @param str* @return*/public static String stringArrayToString(String[] str) {return stringArrayToString(str, "");}/*** 将字符数组转换成字符串* * @param str* @param separator*            各个字符串之间的分隔符* @return*/public static String charArrayToString(char[] ch, String separator) {StringBuffer sb = new StringBuffer();for (int i = 0; i < ch.length; i++) {sb.append(ch[i]);if (ch.length != (i + 1)) {sb.append(separator);}}return sb.toString();}/*** 将字符数组转换成字符串* * @param str* @return*/public static String charArrayToString(char[] ch) {return charArrayToString(ch, " ");}/*** 取汉字的首字母* * @param src* @param isCapital*            是否是大写* @return*/public static char[] getHeadByChar(char src, boolean isCapital) {// 如果不是汉字直接返回if (src <= 128) {return new char[] { src };}// 获取所有的拼音String[] pinyingStr = PinyinHelper.toHanyuPinyinStringArray(src);// 创建返回对象int polyphoneSize = pinyingStr.length;char[] headChars = new char[polyphoneSize];int i = 0;// 截取首字符for (String s : pinyingStr) {char headChar = s.charAt(0);// 首字母是否大写,默认是小写if (isCapital) {headChars[i] = Character.toUpperCase(headChar);} else {headChars[i] = headChar;}i++;}return headChars;}/*** 取汉字的首字母(默认是大写)* * @param src* @return*/public static char[] getHeadByChar(char src) {return getHeadByChar(src, true);}/*** 查找字符串首字母* * @param src* @return*/public static String[] getHeadByString(String src) {return getHeadByString(src, true);}/*** 查找字符串首字母* * @param src* @param isCapital*            是否大写* @return*/public static String[] getHeadByString(String src, boolean isCapital) {return getHeadByString(src, isCapital, null);}/*** 查找字符串首字母* * @param src* @param isCapital*            是否大写* @param separator*            分隔符* @return*/public static String[] getHeadByString(String src, boolean isCapital,String separator) {char[] chars = src.toCharArray();String[] headString = new String[chars.length];int i = 0;for (char ch : chars) {char[] chs = getHeadByChar(ch, isCapital);StringBuffer sb = new StringBuffer();if (null != separator) {int j = 1;for (char ch1 : chs) {sb.append(ch1);if (j != chs.length) {sb.append(separator);}j++;}} else {sb.append(chs[0]);}headString[i] = sb.toString();i++;}return headString;}public static void main(String[] args) {// pin4j 简码 和 城市编码 String s1 = "中华人民共和国"; String[] headArray = getHeadByString(s1); // 获得每个汉字拼音首字母System.out.println(Arrays.toString(headArray));String s2 ="长城" ; System.out.println(Arrays.toString(stringToPinyin(s2,true,",")));String s3 ="长";System.out.println(Arrays.toString(stringToPinyin(s3,true,",")));}
}



2.    区域分页查询

    修改region.jsp页面中datagrid的url地址

    在RegionAction中提供分页查询方法pageQuery

与上一天的代码重复需要提取到baseAction  


3.    重构分页代码

    在BaseAction中提取PageBean和DetachedCriteria对象

	protected PageBean pageBean = new PageBean();// 离线条件查询对象,用于包装查询条件DetachedCriteria detachedCriteria = null;

    在BaseAction中提供setPage和setRows方法

把分页ajax相应的两个参数row和page直接注入到上面提取的pageBean中

	public void setPage(int page) {pageBean.setCurrentPage(page);// 当前页码}public void setRows(int rows) {pageBean.setPageSize(rows);// 每页显示记录数}

    在BaseAction的构造方法中创建离线条件查询对象,并且注入给PageBean

 构造方法获取实体类型后创建离线查询条件对象并注入到pageBean中

	public BaseAction() {// 获得父类(BaseAction) 类型ParameterizedType superclass = (ParameterizedType) this.getClass().getGenericSuperclass();// 获得父类上的泛型数组Type[] typeArguments = superclass.getActualTypeArguments();// 获得实体类型Class domainClass = (Class) typeArguments[0];// 获得实体类型后创建离线条件查询对象detachedCriteria = DetachedCriteria.forClass(domainClass);pageBean.setDetachedCriteria(detachedCriteria);try {model = domainClass.newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}

    在BaseAction中抽取方法writePageBean2Json和writeListBean2Json

	/*** 将PageBean序列化为json返回*/public void writePageBean2Json(PageBean pageBean, String[] excludes) {// 使用jsonlib将PageBean对象序列化为json数据JsonConfig jsonConfig = new JsonConfig();jsonConfig.setExcludes(excludes);String json = JSONObject.fromObject(pageBean, jsonConfig).toString();ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8");try {ServletActionContext.getResponse().getWriter().print(json);} catch (IOException e) {e.printStackTrace();}}/*** 将List序列化为json返回*/public void writeListBean2Json(List list, String[] excludes) {// 使用jsonlib将PageBean对象序列化为json数据JsonConfig jsonConfig = new JsonConfig();jsonConfig.setExcludes(excludes);String json = JSONArray.fromObject(list, jsonConfig).toString();ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8");try {ServletActionContext.getResponse().getWriter().print(json);} catch (IOException e) {e.printStackTrace();}}
 

    在RegionAction中的分页查询

分页查询代码简化为3条

	/*** 分页查询方法* @throws IOException */public String pageQuery() throws IOException{regionService.pageQuery(pageBean);this.writePageBean2Json(pageBean, new String[]{"currentPage","pageSize","detachedCriteria","subareas"});return NONE;}

  

4.    分区添加功能


4.1   Combobox下拉框使用

方式一:给静态的select标签应用

方式二:使用input标签通过url动态获取数据(json)

textField:为"option"下拉显示的内容

valueField::为最终提交的value值




subarea分区页面的添加分区弹窗区域选择下拉框数据获取(模糊查询)

及添加分区功能

 

第一步:修改subarea.jsp页面中combobox的url地址


mode属性

定义了当文本改变时如何读取列表数据。设置为'remote'时,下拉列表框将会从服务器加载数据。

当设置为“remote”模式时,用户输入将被发送到名为'q'的HTTP请求参数到服务器检索新数据。

 

						  

对应分区类也应增加与下拉栏textField对应的name属性(省市区)

	private String id;//编号private String province;//省private String city;//市private String district;//区private String postcode;//邮编private String shortcode;//简码private String citycode;//城市编码private Set subareas = new HashSet(0);//区域对应的多个分区public String getName(){return province + city + district;}


第二步:在RegionAction中提供list方法查询区域数据

 

	private String q;//模糊查询参数	public void setQ(String q) {this.q = q;}/***  查询所有区域返回json*/public String list(){List list = null;if(StringUtils.isNotBlank(q)){//根据q进行模糊查询list = regionService.findByQ(q.trim());}else{//查询所有list = regionService.findAll();}String[] excludes = new String[]{"subareas"};this.writeListBean2Json(list, excludes);return NONE;}

Service中:

	@Overridepublic List findByQ(String q) {	return regionDao.findByNameQuery("findByQ","%"+q+"%","%"+q+"%","%"+q+"%");}
baseIDaompl命名查询

	@Overridepublic List findByNameQuery(String hqlName, Object... params) {List findByNamedQuery = this.getHibernateTemplate().findByNamedQuery(hqlName,params);return findByNamedQuery;}

对应*hbm.xml提供query hql语句

注意:命名查询配置语句中不能出现双引号" "会报错,因为语句是按字符串来提取的,xml配置+" "来拼接也不行

    FROM Region WHERE city LIKE ? OR province LIKE ? OR district LIKE ? 

第三步:为保存按钮绑定事件

				保存 

第四步:创建一个SubareaAction,提供add方法用于添加分区

 略

 

5.    分区组合条件分页查询

基于datagrid的load方法实现组合条件分页查询

 

*带关联查询的分页查询转换json会出错

freemarker.template.TemplateModelException:

Method public java.lang.Stringorg.apache.commons.lang.exception

.NestableRuntimeException.getMessage(int)threw an exception when invoked on net.sf.json.JSONException:

java.lang.reflect.InvocationTargetException

原因:关联对象延迟加载是代理对象无法转换成json数据

解决: 修改对应需关联对象hbm,xml文件的lazy属性为false 解决关联查询问题

        

第一步:提供组合条件查询窗口

第二步提供一个工具方法,将form表单中的输入项转为json数据,提交参数

	$.fn.serializeJson=function(){  var serializeObj={};  var array=this.serializeArray();$(array).each(function(){  if(serializeObj[this.name]){  if($.isArray(serializeObj[this.name])){  serializeObj[this.name].push(this.value);  }else{  serializeObj[this.name]=[serializeObj[this.name],this.value];  }  }else{  serializeObj[this.name]=this.value;   }  });  return serializeObj;  }; 


第三步:为查询按钮绑定事件,调用datagrid的load方法,重写发起ajax请求,提交参数

目的:这样发起的查询是ajax请求,条件参数会缓存在页面.

ajax没有全部刷新页面所以对应分页查询的条件也不会丢失


方法:load       

参数:param

详情:

加载和显示第一页的所有行。如果指定了'param',它将取代'queryParams'属性。通常可以通过传递一些参数执行一次查询,通过调用这个方法从服务器加载新数据。



 

	


第四步:改造SubareaAction中的pageQuery方法,加入组合条件分页查询逻辑


Restrictions  API


	/*** 分页组合条件查询*/public String pageQuery() {DetachedCriteria subareaDC = pageBean.getDetachedCriteria();// 从模型对象中获取提交的查询参数String addresskey = model.getAddresskey();// 关键字// 单表查询if (StringUtils.isNotBlank(addresskey)) {// 添加查询条件,根据关键字进行模糊查询subareaDC.add(Restrictions.like("addresskey","%" + addresskey.trim() + "%"));}Region region = model.getRegion();// 多表查询if (region != null) {String province = region.getProvince();String city = region.getCity();String district = region.getDistrict();DetachedCriteria regionDC = subareaDC.createCriteria("region");if (StringUtils.isNotBlank(province)) {// 添加查询条件,根据省进行模糊查询regionDC.add(Restrictions.like("province", "%" + province + "%"));}if (StringUtils.isNotBlank(city)) {// 添加查询条件,根据省进行模糊查询regionDC.add(Restrictions.like("city", "%" + city + "%"));}if (StringUtils.isNotBlank(district)) {// 添加查询条件,根据省进行模糊查询regionDC.add(Restrictions.like("district", "%" + district + "%"));}}subareaService.pageQuery(pageBean);String[] excludes = new String[] { "decidedzone", "subareas" };this.writePageBean2Json(pageBean, excludes);return NONE;}

 

6.    分区数据导出功能(Excel提供下载)

第一步:修改subarea.jsp页面中导出按钮的事件 

	function doExport(){//发起请求Action,查询所有分区数据,写到Excel文件中并提供下载window.location.href = "${pageContext.request.contextPath}/subareaAction_exportXls.action";}

第二步:在Action中提供exportXls方法

两种方法:

方式一:原始手动设置响应下载

文件名乱码工具类

import java.io.IOException;
import java.net.URLEncoder;import sun.misc.BASE64Encoder;public class FileUtils {/*** 下载文件时,针对不同浏览器,进行附件名的编码* * @param filename*            下载文件名* @param agent*            客户端浏览器* @return 编码后的下载附件名* @throws IOException*/public static String encodeDownloadFilename(String filename, String agent)throws IOException {if (agent.contains("Firefox")) { // 火狐浏览器filename = "=?UTF-8?B?"+ new BASE64Encoder().encode(filename.getBytes("utf-8"))+ "?=";filename = filename.replaceAll("\r\n", "");} else { // IE及其他浏览器filename = URLEncoder.encode(filename, "utf-8");filename = filename.replace("+"," ");}return filename;}
}


	/*** 导出分区数据到Excel文件并提供下载* * @throws IOException*/public String exportXls() throws IOException {List list = subareaService.findAll();// 使用POI将查询的数据写入Excel文件中HSSFWorkbook workbook = new HSSFWorkbook();// 在工作表中创建一个sheet页HSSFSheet sheet = workbook.createSheet("分区数据");// 创建标题行HSSFRow headRow = sheet.createRow(0);// 创建单元格headRow.createCell(0).setCellValue("分区编号");headRow.createCell(1).setCellValue("关键字");headRow.createCell(2).setCellValue("地址");headRow.createCell(3).setCellValue("省市区");for (Subarea subarea : list) {// 创建数据行HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1);String id = subarea.getId();String addresskey = subarea.getAddresskey();String position = subarea.getPosition();Region region = subarea.getRegion();dataRow.createCell(0).setCellValue(id);dataRow.createCell(1).setCellValue(addresskey);dataRow.createCell(2).setCellValue(position);if (region != null) {String province = region.getProvince();String city = region.getCity();String district = region.getDistrict();String info = province + city + district;dataRow.createCell(3).setCellValue(info);}}String filename = "分区数据.xls";String agent = ServletActionContext.getRequest().getHeader("user-agent");//浏览器类型filename = FileUtils.encodeDownloadFilename(filename, agent );//根据文件名称动态获得类型String contentType = ServletActionContext.getServletContext().getMimeType(filename);// 通知客户端下载文件的类型ServletActionContext.getResponse().setContentType(contentType);//指定以附件形式下载,指定文件名称ServletActionContext.getResponse().setHeader("content-disposition", "attachment;filename=" + filename);// 通过输出流向客户端浏览器写Excel文件ServletOutputStream out = ServletActionContext.getResponse().getOutputStream();workbook.write(out);return NONE;}
}


方式二:通过struts2的stream结果集下载


思路百度自博客(http://xiaowei-qi-epro-com-cn.iteye.com/blog/2030671):

思路是,先创建一个输出流,将这个excel写入到输出流里面,然后再通过这个输出流来得到我们所需要的输入流.

使用了ByteArrayOutputStreamByteArrayInputStream...处理的思想是,HSSFWorkbook 写入ByteArrayOutputStream.然后用ByteArrayOutputStream来转换为字节流..然后再将字节流转换为ByteArrayInputStream ..至此,我们就在内存中将excel转换成了输入流

	private InputStream target;  public InputStream getTarget() {  return target;  } //下载文件名,存在中文乱码  private String downloadFileName;  public String getDownloadFileName() throws UnsupportedEncodingException {  // 处理中文乱码  if(downloadFileName != null){  return new String(downloadFileName.getBytes("GBK"),"ISO-8859-1");  }  return downloadFileName;  }  /*** 下载所有分区信息以xls格式* @return* @throws IOException */public String export() throws IOException{List list=subareaService.findAll();//把list写入excel文档HSSFWorkbook book=new HSSFWorkbook();HSSFSheet sheet = book.createSheet("全部分区详情");//创建初始标题行HSSFRow row = sheet.createRow(0);row.createCell(0).setCellValue("分拣编号");row.createCell(1).setCellValue("省市区");row.createCell(2).setCellValue("关键字");row.createCell(3).setCellValue("位置");//遍历listfor (Subarea subarea : list) {HSSFRow createRow = sheet.createRow(sheet.getLastRowNum()+1);String id = subarea.getId();String nameInfo = subarea.getRegion().getName();String addresskey = subarea.getAddresskey();String position = subarea.getPosition();createRow.createCell(0).setCellValue(id);createRow.createCell(1).setCellValue(nameInfo);createRow.createCell(2).setCellValue(addresskey);createRow.createCell(3).setCellValue(position);}ByteArrayOutputStream out = new ByteArrayOutputStream();book.write(out);target = new ByteArrayInputStream(out.toByteArray());  out.close();  downloadFileName="分区详情.xls";		return "download";}
 

 

配置文件

		/WEB-INF/pages/base/subarea.jsp			    attachment;filename=${downloadFileName}    target   			



本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部