MySQL版本5.7,基于java的服务器
1.获取导出文件权限
数据库/表设置权限时经常会
mysql>grant all privileges on databasename.tablename to username@localhost;
mysql>flush priviliges;
来获取所有权限,但是需要注意的是这里面并没有包括允许导出文件的权限,相关权限需要单独设置
mysql>grant file on *.* to username@localhost;
在数据库和表的范围上要设置为全部,即”.“。
2.确定输出文件位置
MySQL在导出文件位置上也有安全保护限制,限定了用户只能将文件导出到指定文件夹下,否则操作失败,而指定的文件夹为secure_file_priv变量的值,可以通过命令行查看,windows下可在my.ini文件中找到,同时也可在my.ini文件中进行修改来适应开发的需要,修改后重新启动即生效。
在这里有笔者一点经验在于文件路径的写法,windows中使用反斜杠’\’而Linux使用斜杠’/’,在windows上my.ini中仍使用’/’,而windows上命令行查询结果使用’\’显示,在笔者个人在windows和centos上操作的情况来看,在导出文件路径书写上都使用’/’即可,具体实例可参考下文。
3.导出文件
以Linux下默认文件路径/var/lib/mysql-files/为例
mysql>select * from filename into outfile '/var/lib/mysql-files/filename.xls';
操作后可在对应位置获取文件。
4.文件转码
通常安装MySQL时我们会将字符集设置为UTF-8来获得更好的通用性,但是鉴于我们windows上Excle解码默认为GBK,因此按上述步骤生成的.xls文件直接下载打开会出现乱码,要解决这一问题,一个有效的方法是在服务器端将文件写入发送流时进行转码。
protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
// TODO Auto-generated method stub
/*
生成.xls文件的操作;
*/
//获取文件读入流与下载输出流
BufferedInputStream ins=new BufferedInputStream(new
FileInputStream(xlsPath+fileName);
BufferedOutputStream outs=new
BufferedOutputStream(response.getOutputStream());
//http协议头
response.setHeader("Content-Disposition",
"attachment;filename="+fileName);
byte[] bytes=new byte[ins.available()];//保存原文件的字节编码
byte[] buffer;//保存转码后的文件字节编码
String temp=null;//暂存文件字符编码
temp=new String(bytes,"utf-8");
buffer=temp.getBytes("gbk");
outs.write(buffer);
outs.flush();
outs.close();
}
另外关于bytes数组的长度设置上,笔者最初看到许多人分享的方法是设置为定长,多次读取文件的字节转码发送,大致如下
byte[] bytes=new byte[2048];
byte buffer;
String temp=null;
int read=0;
while((read=ins.read(bytes))!=-1){
temp=new String(bytes,"utf-8");
buffer=temp.getBytes("gbk",0,read);
outs.write(buffer);
}
outs.flush();
outs.close();
而在实际应用中笔者发现这样下载的文件,在个别部分仍然存在少量乱码,个人猜测是两次读取字节转码衔接的部分导致了乱码,具体原因还有待对jdk源码的考量。