使用数据库(mysql)字段保存文件

数据库:mysql + mybatis

文件:本项目保存的是excel文件,其他文件应该也是适用的

最近由于项目原因,需将文件保存到数据库中,最先开始设计新增一个类型为blob的字段,结果保存没有问题,但下载的时候如果该excel文件里包含特殊公式,或者版本不兼容时,会丢失样式和内容,最终解决方式:将bolb类型改为mediumtext(或则text),text最大支持64kb的文件,mediumtext最大支持16M的文件,可视情况进行设置

 

例如:alter table ab_report_history add column fileContent mediumtext COMMENT '文件内容';

 

重点:保存时将文件转换为String后,base64编码,下载时将内容取出来,base64解码

 

示例:

java代码:

保存时:

 AbReportHistory record = new AbReportHistory();
 record.setFileContent(FileUtil.encodeBase64File(myfile)); //注意此方法

 

下载时:

new BASE64Decoder().decodeBuffer(编码后的string); //通过此方法解码

java字段类型:

private String fileContent;

 

mybatis

<result column="fileContent" jdbcType="VARCHAR" property="fileContent" />

 

--------------------------------以上是将文件保存到数据库的关键内容--------------------------------------------------------

 

以下提供相关工具类:

package *.*.*.*;
 
 
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
 
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.web.multipart.MultipartFile;
 
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
 
/**
 * 文件操作工具类
 * @author sunddylee
 * @date 2016年12月20日
 * 
 */
public class FileUtil {
	
	/**
	 * NIO way 
	 * 读取excel文件
	 * @param filePath
	 * @param fileName
	 * @throws Exception
	 */
	public static byte[] readExcelFiletoByteArray(String filePath) throws Exception {
		File f = new File(filePath);  
        if (!f.exists()) {  
            throw new FileNotFoundException(filePath);  
        }  
  
        FileChannel channel = null;  
        FileInputStream fs = null;  
        try {  
            fs = new FileInputStream(f);  
            channel = fs.getChannel();  
            ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());  
            while ((channel.read(byteBuffer)) > 0) {  
                // do nothing  
                // System.out.println("reading");  
            }  
            return byteBuffer.array();  
        } catch (IOException e) {  
            e.printStackTrace();  
            throw e;  
        } finally {  
            try {  
                channel.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            try {  
                fs.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }
	
	/**
	 * 下载excel文件
	 * @param response
	 * @param filePath
	 * @param fileName:带有后缀名的文件名 例如 a.xls
	 * @throws Exception
	 */
    public static void downloadExcelFile(HttpServletResponse response, String filePath, String fileName) throws Exception {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            // 设置response参数,可以打开下载页面
            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename="
                    + new String((fileName).getBytes(), "iso-8859-1"));
            ServletOutputStream out = response.getOutputStream();
 
            bis = new BufferedInputStream(new FileInputStream(filePath));
            bos = new BufferedOutputStream(out);
 
            byte[] buff = new byte[2048];
            int bytesRead;
            // Simple read/write loop.
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
        } catch (IOException e) {
            throw e;
        } finally {
            if (bis != null)
                bis.close();
            if (bos != null)
                bos.close();
        }
    }
    
    public static void downloadExcelFile(HttpServletResponse response, String fileName, byte[] fileContent) throws Exception {
    	BufferedOutputStream bos = null;
    	try {
            // 设置response参数,可以打开下载页面
            response.reset();
            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename="
                    + new String((fileName).getBytes(), "iso-8859-1"));
            ServletOutputStream out = response.getOutputStream();
            bos = new BufferedOutputStream(out);
            if(null != fileContent){
            	bos.write(fileContent);
            }
            
        } catch (IOException e) {
            throw e;
        } finally {
            if (bos != null)
                bos.close();
        }
    }
    
    /** 
     * 将文件转成base64 字符串 
     * @param path文件路径 
     * @return  *  
     * @throws Exception 
     */  
    public static String encodeBase64File(String path) throws Exception {  
    	File file = new File(path);
		FileInputStream inputFile = new FileInputStream(file);  
		byte[] buffer = new byte[(int) file.length()];  
		inputFile.read(buffer);  
		inputFile.close();  
		return new BASE64Encoder().encode(buffer);  
    }  
     
    
    public static String encodeBase64File(MultipartFile file) throws Exception {  
		return new BASE64Encoder().encode(file.getBytes());  
    }  
    
    public static byte[] decoderBase64File(String base64Code) throws Exception { 
    	return new BASE64Decoder().decodeBuffer(base64Code);  
    }  
    
    
    /** 
     * 将base64字符解码保存文件 
     * @param base64Code 
     * @param targetPath 
     * @throws Exception 
     */  
    public static void decoderBase64File(String base64Code, String targetPath)  
      throws Exception {  
    	byte[] buffer = new BASE64Decoder().decodeBuffer(base64Code);  
    	FileOutputStream out = new FileOutputStream(targetPath);  
    	out.write(buffer);  
    	out.close();  
    }  
     
    /** 
     * 将base64字符保存文本文件 
     * @param base64Code 
     * @param targetPath 
     * @throws Exception 
     */  
     
    public static void toFile(String base64Code, String targetPath)  
      throws Exception {  
    	byte[] buffer = base64Code.getBytes();  
    	FileOutputStream out = new FileOutputStream(targetPath);  
    	out.write(buffer);  
    	out.close();  
    }  
     
    public static void main(String[] args) {  
     try {  
      String base64Code = encodeBase64File("E:\\test\\test1.xls");  
      System.out.println(base64Code);  
      decoderBase64File(base64Code, "E:\\test\\test.xls");  
//      toFile(base64Code, "D:\\three.txt");  
     } catch (Exception e) {  
      e.printStackTrace();  
     
     }  
     
    }  
}

MySQL之text字段

 

TEXT类型一般分为 TINYTEXT(255长度)、TEXT(65535)相当于64k、 MEDIUMTEXT(int最大值16M),和LONGTEXT(long最大值4G)这四种,它被用来存储非二进制字符集,二进制字符集使用blob类型的字段来存储。

对于text列,插入时MySQL不会对它进行填充,并且select时不会删除任何末尾的字节。

如果text列被作为索引,则在它的内容后面添加空格时,会出现duplicate key错误,也就是说,如果我们定义了一个作为索引的text字段,它的值是'a',则不能定义一个值为'a '的记录,因为这样会产生冲突。

对text列进行排序的时候,决定顺序的字符个数是由参数max_sort_length来决定的

text和varchar的区别

SET max_sort_length=1000; 
SELECT id,comment FROM table ORDER BY comment;

在大多数情况下,我们可以把text视为varchar字段,但是这两个字段类型在存储字符大小上有一些区别:

    varchar在mysql中必须满足最大行宽度限制,也就是 65535(64k)字节,而varchar本身是按字符串个数来定义的,在mysql中使用uft-8字符集一个字符占用三个字节,所以单表varchar实际占用最大长度如下:
    1.使用utf-8字符编码集varchar最大长度是(65535-2)/3=21844个字符(超过255个字节会有2字节的额外占用空间开销,所以减2,如果是255以下,则减1)。
    2.使用 utf-8mb4字符集,mysql中使用 utf-8mb4 字符集一个字符占用4个字节,所以 varchar 最大长度是(65535-2)/4=16383 个字符(超过255个字节会有2字节的额外占用空间开销,所以减2,如果是255以下,则减1)。

    text的最大限制也是64k个字节,但是本质是溢出存储,innodb默认只会存放前768字节在数据页中,而剩余的数据则会存储在溢出段中。text类型的数据,将被存储在元数据表之外地方,但是varchar/char将和其他列一起存储在表数据文件中,值得注意的是,varchar列在溢出的时候会自动转换为text类型。text数据类型实际上将会大幅度增加数据库表文件尺寸。

    除此之外,二者还有以下的区别

1、当text作为索引的时候,必须 制定索引的长度,而当varchar充当索引的时候,可以不用指明。

2、text列不允许拥有默认值

3、当text列的内容很多的时候,text列的内容会保留一个指针在记录中,这个指针指向了磁盘中的一块区域,当对这个表进行select *的时候,会从磁盘中读取text的值,影响查询的性能,而varchar不会存在这个问题。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值