SpringBoot 中使用MongoDB GridFs

接上述文章内容开始,mongodb要做数据仓储,最重要的还是存储,这里指的存储是文件存储,mongodb自带强大的文件分片存储技术,GridFs技术
GridFs技术

附上官方文献资料:https://docs.mongodb.com/manual/core/gridfs/index.html
那么,什么情况下才适用mongodb自带的GridFs技术呢?
答: 适用存储大型文件,单文件>16M
那么,又有人会问了,那些单文件<16M的应该怎么存储?
答: 可以考虑将每个文件存储在单个文档中,用BinData数据类型存储二进制数据
以上参考官方文献资料给出一些答复

说到分片存储肯定离不开系统两个存储相关的表

  • fs.chunks:集合中的每个文档代表GridFS中表示的文件的不同块
    在这里插入图片描述

    _id:该文档的唯一标识符
    files_id:fs.files中_id 外键
    n:表示当前为fs.files中_id对应文件的序列化
    data:分片存储的内容

  • fs.files:集合中的每个文档代表GridFS中的一个文件
    在这里插入图片描述

    _id:该文档的唯一标识符
    filename:GridFS文件的可读名称
    length:文档的大小(以字节为单位)
    chunkSize:每个块的大小(以字节为单位
    uploadDate:GridFS首次存储文档的日期
    md5:完整文件的MD5哈希
    metadata:元数据字段可以是任何数据类型,并且可以包含您要存储的任何其他信息

在springboot项目中使用GridFs

以下内容承接上篇文章内容,《在springboot中使用mongodb》
1、MongoDB配置类

import com.mongodb.MongoClientSettings;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

/**
 * mongoDB 配置类
 */
@Configuration
public class MongoConfig {


    @Value("${spring.data.mongodb.host}")
    private String host;

    @Value("${spring.data.mongodb.port}")
    private Integer port;

    @Value("${spring.data.mongodb.database}")
    private String database;

    @Bean
    public MongoClient getMongoClient(){
        MongoClient mongoClient = MongoClients.create(
                MongoClientSettings.builder()
                        .applyToClusterSettings(builder ->
                                builder.hosts(Arrays.asList(new ServerAddress(host, port))))
                        .build());
        return mongoClient;
    }

    @Bean
    public GridFSBucket getgridFSBucket(MongoClient mongoClient) {
        MongoDatabase mongoDatabase = mongoClient.getDatabase(database);
        GridFSBucket gridFSBucket = GridFSBuckets.create(mongoDatabase);
        return gridFSBucket;
    }
}

2、GridFs公用类

import java.io.InputStream;
import java.util.Optional;

public interface IFileService {

    String uploadFileToGridFS(InputStream in , String contentType);

    void removeFile(String id, boolean isDeleteFile, String gridfsId, String collectionName);

    Optional<?> getById(String id, String gridfsId, Class<?> clazz);

}
import com.java.common.utils.IoUtil;
import com.java.service.IFileService;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.mongodb.client.result.DeleteResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.UUID;

@Service
public class FileService implements IFileService {

    private MongoTemplate mongoTemplate;

    private GridFsTemplate gridFsTemplate;

    private GridFSBucket gridFSBucket;


    @Autowired
    public FileService(MongoTemplate mongoTemplate, GridFsTemplate gridFsTemplate, GridFSBucket gridFSBucket) {
        this.mongoTemplate = mongoTemplate;
        this.gridFsTemplate = gridFsTemplate;
        this.gridFSBucket = gridFSBucket;
    }

    /**
     * 上传文件到Mongodb的GridFs中
     * @param in
     * @param contentType
     * @return
     */
    @Override
     public String uploadFileToGridFS(InputStream in , String contentType){
        String gridfsId = UUID.randomUUID().toString();
        //文件,存储在GridFS中
        gridFsTemplate.store(in, gridfsId , contentType);
        return gridfsId;
    }

    /**
     * 删除附件
     * @param id 文件id
     * @param isDeleteFile 是否删除文件
     */
    @Override
    public void removeFile(String id, boolean isDeleteFile, String gridfsId, String collectionName) {
        //移除删除的文件信息数据,如文件名,文件类型。。。。
        Query query = new Query().addCriteria(Criteria.where("_id").is(id));
        DeleteResult result = mongoTemplate.remove(query , collectionName);
        System.out.println("result:" + result.getDeletedCount());
        //判断是否物理删除分布式存储的文件
        if(isDeleteFile){
            Query deleteQuery = new Query().addCriteria(Criteria.where("filename").is(gridfsId));
            gridFsTemplate.delete(deleteQuery);
        }
    }

    /**
     * 查询附件
     * @param id 文件id
     * @return
     * @throws IOException
     */
    public Optional<?> getById(String id, String gridfsId, Class<?> clazz){
        try {
            Object obj = mongoTemplate.findById(id , clazz , clazz.getDeclaredAnnotation(Document.class).value());
            if(obj != null){
                //根据关联查询gridFs中的附件 gridfsId <==> fs.files中filename
                Query gridQuery = new Query().addCriteria(Criteria.where("filename").is(gridfsId));
                //在fs.files集合下查找关联fs.chunks的id
                GridFSFile fsFile = gridFsTemplate.findOne(gridQuery);
                //fs.files中_id <==> fs.chunks中files_id
                //根据fs.chunks中的files_id(文件id)获取所有文件内容块
                GridFSDownloadStream in = gridFSBucket.openDownloadStream(fsFile.getObjectId());
                if(in.getGridFSFile().getLength() > 0){
                    GridFsResource resource = new GridFsResource(fsFile, in);
                    Method method = clazz.getMethod("setContent", byte[].class);
                    method.invoke(obj, IoUtil.toByteArray(resource.getInputStream()));
                    return Optional.of(obj);
                }else {
                    obj = null;
                    return Optional.empty();
                }
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return Optional.empty();
    }
}

3、调用公共类

import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;

@Data
@Document("dimensional_model")
public class DimensionalModel {

    private String _id;

    private String gridFsId;

    private byte[] content;

    private String fileName;

    private String fileType;

    private String dimension;

    private String warehousingTime;

    private String updateTime;

    private String remark;

}
import com.java.common.Page;
import com.java.common.ResultMsg;
import com.java.common.utils.DateUtils;
import com.java.common.utils.DownloadFileUtils;
import com.java.common.utils.WebUtils;
import com.java.service.IDimensionalModelService;
import com.java.service.IFileService;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class DimensionalModelService implements IDimensionalModelService {



    private MongoTemplate mongoTemplate;

    private IFileService fileService;

    private IDataService dataService;



    @Autowired
    public DimensionalModelService(MongoTemplate mongoTemplate, IFileService fileService, IDataService dataService) {
        this.mongoTemplate = mongoTemplate;
        this.fileService = fileService;
        this.dataService = dataService;
    }

    private final static String collectionName = DimensionalModel.class.getDeclaredAnnotation(Document.class).value();

    @Override
    public ResultMsg<?> resolveFile(MultipartFile[] files, String... params) {
        String dimension = params[0];
        ResultMsg<DimensionalModel> resultMsg = new ResultMsg<>();
        String msg = "";
        //使用gridFs技术文件分段存储
        uploadFilesWithDimension(legitimateFiles, dimension);
       	//省略........
        resultMsg.setMsg(msg);
        return resultMsg;
    }

    private void uploadFilesWithDimension(List<MultipartFile> legitimateFiles, String dimension) {
        DimensionalModel dimensionalModel = null;
        String fileName = "";
        String suffix = "";
        //设置批量导入的量
        int batch_insert = 1000;
        List<DimensionalModel> dimensionalModelList = new ArrayList<>();
        try {
            for (MultipartFile file: legitimateFiles
                    ) {
                fileName= file.getOriginalFilename().substring(file.getOriginalFilename().indexOf("/")+1,
                        file.getOriginalFilename().lastIndexOf("."));
                suffix= file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
                dimensionalModel = new DimensionalModel();
                dimensionalModel.setDimension(dimension);
                dimensionalModel.setFileName(fileName);
                dimensionalModel.setFileType(suffix);
                dimensionalModel.setWarehousingTime(DateUtils.getStrDate("yyyy-MM-dd HH:mm:ss"));
                dimensionalModel.setUpdateTime(DateUtils.getStrDate("yyyy-MM-dd HH:mm:ss"));
                //使用gridFs技术文件分段存储
                String gridFsId = fileService.uploadFileToGridFS(file.getInputStream(), file.getContentType());
                dimensionalModel.setGridFsId(gridFsId);
                //将维度模型结果数据保存到数据库中
                dimensionalModelList.add(dimensionalModel);
                //保存数据
                if (dimensionalModelList.size()>=batch_insert) {
                    mongoTemplate.insert(dimensionalModelList, collectionName);
                    dimensionalModelList.clear();
                }
            }
            mongoTemplate.insert(dimensionalModelList, collectionName);
            dimensionalModelList.clear();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void download(String id) {
        String fileName = "";
        try {
            //根据id条件获取上传毛语料信息
            Criteria criteria = new Criteria("_id").is(id);
            Query query = new Query(criteria);
            DimensionalModel dimensionalModel = mongoTemplate.findOne(query, DimensionalModel.class);
            fileName = dimensionalModel.getFileName() + dimensionalModel.getFileType();
            //解析数据,下载文件
            Optional<DimensionalModel> optional =  (Optional<DimensionalModel>)fileService.
                                                    getById(dimensionalModel.get_id(),
                                                    dimensionalModel.getGridFsId(),
                                                    DimensionalModel.class);
            //下载文件
            DownloadFileUtils.getFileByBytes(WebUtils.getResponse(), optional.get().getContent(), fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Page<?> getList(Integer offset, Integer page_size, String dimension) {
        Page<DimensionalModel> materialPage = new Page<>();

        //查询条件  根据维度查询
        Criteria criteria = new Criteria();

        if (Strings.isNotBlank(dimension)) {
            criteria = criteria.where("dimension").is(dimension);
        }

        materialPage.setPageNo((offset/page_size)+1);
        materialPage.setPageSize(page_size);
        materialPage.setSkip(offset);
        //将查询条件设置到查询类中
        Query query = new Query(criteria);

        int count = (int)mongoTemplate.count(query, collectionName);
        materialPage.setTotal(count);

        query.skip(materialPage.getSkip()).limit(materialPage.getPageSize());

        List<DimensionalModel> dimensionalModelList = mongoTemplate.find(query,
                DimensionalModel.class);

        materialPage.setRows(dimensionalModelList);
        return materialPage;
    }
}

以下是上面代码中使用到的工具类
IoUtil

import javax.validation.constraints.NotNull;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class IoUtil {

	private static final int BUFFER_SIZE = 1024 * 8;

	public static byte[] toByteArray(InputStream input) throws IOException {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		copy(input, output);
		return output.toByteArray();
	}

	public static int copy(InputStream input, OutputStream output) throws IOException {
		long count = copyLarge(input, output);
		if (count > 2147483647L) {
			return -1;
		}
		return (int) count;
	}

	public static long copyLarge(InputStream input, OutputStream output) throws IOException {
		byte[] buffer = new byte[4096];
		long count = 0L;
		int n = 0;
		while (-1 != (n = input.read(buffer))) {
			output.write(buffer, 0, n);
			count += n;
		}
		return count;
	}

	/**
	 * write.
	 *
	 * @param is InputStream instance.
	 * @param os OutputStream instance.
	 * @return count.
	 * @throws IOException
	 */
	public static long write(InputStream is, OutputStream os) throws IOException
	{
		return write(is, os, BUFFER_SIZE);
	}

	/**
	 * write.
	 *
	 * @param is InputStream instance.
	 * @param os OutputStream instance.
	 * @param bufferSize buffer size.
	 * @return count.
	 * @throws IOException
	 */
	public static long write(InputStream is, OutputStream os, int bufferSize) throws IOException
	{
		int read;
		long total = 0;
		byte[] buff = new byte[bufferSize];
		while( is.available() > 0 )
		{
			read = is.read(buff, 0, buff.length);
			if( read > 0 )
			{
				os.write(buff, 0, read);
				total += read;
			}
		}
		return total;
	}

	/**
	 * read string.
	 *
	 * @param reader Reader instance.
	 * @return String.
	 * @throws IOException
	 */
	public static String read(Reader reader) throws IOException
	{
		StringWriter writer = new StringWriter();
		try
		{
			write(reader, writer);
			return writer.getBuffer().toString();
		}
		finally{ writer.close(); }
	}

	/**
	 * write string.
	 *
	 * @param writer Writer instance.
	 * @param string String.
	 * @throws IOException
	 */
	public static long write(Writer writer, String string) throws IOException
	{
		Reader reader = new StringReader(string);
		try{ return write(reader, writer); }finally{ reader.close(); }
	}

	/**
	 * write.
	 *
	 * @param reader Reader.
	 * @param writer Writer.
	 * @return count.
	 * @throws IOException
	 */
	public static long write(Reader reader, Writer writer) throws IOException
	{
		return write(reader, writer, BUFFER_SIZE);
	}

	/**
	 * write.
	 *
	 * @param reader Reader.
	 * @param writer Writer.
	 * @param bufferSize buffer size.
	 * @return count.
	 * @throws IOException
	 */
	public static long write(Reader reader, Writer writer, int bufferSize) throws IOException
	{
		int read;
		long total = 0;
		char[] buf = new char[BUFFER_SIZE];
		while( ( read = reader.read(buf) ) != -1 )
		{
			writer.write(buf, 0, read);
			total += read;
		}
		return total;
	}

	/**
	 * read lines.
	 *
	 * @param file file.
	 * @return lines.
	 * @throws IOException
	 */
	public static String[] readLines(File file) throws IOException
	{
		if( file == null || !file.exists() || !file.canRead() )
			return new String[0];

		return readLines(new FileInputStream(file), "UTF-8");
	}

	/**
	 * read lines.
	 *
	 * @param is input stream.
	 * @return lines.
	 * @throws IOException
	 */
	public static String[] readLines(InputStream is, @NotNull String charsetName) throws IOException
	{
		List<String> lines = new ArrayList<String>();
		BufferedReader reader = new BufferedReader(new InputStreamReader(is, charsetName));
		try
		{
			String line;
			while( (line = reader.readLine()) != null )
				lines.add(line);
			return lines.toArray(new String[0]);
		}
		finally
		{
			reader.close();
		}
	}

	/**
	 * write lines.
	 *
	 * @param os output stream.
	 * @param lines lines.
	 * @throws IOException
	 */
	public static void writeLines(OutputStream os, String[] lines) throws IOException
	{
		PrintWriter writer = new PrintWriter(new OutputStreamWriter(os));
		try
		{
			for( String line : lines )
				writer.println(line);
			writer.flush();
		}
		finally
		{
			writer.close();
		}
	}

	/**
	 * write lines.
	 *
	 * @param file file.
	 * @param lines lines.
	 * @throws IOException
	 */
	public static void writeLines(File file, String[] lines) throws IOException
	{
		if( file == null )
			throw new IOException("File is null.");
		writeLines(new FileOutputStream(file), lines);
	}

	/**
	 * append lines.
	 *
	 * @param file file.
	 * @param lines lines.
	 * @throws IOException
	 */
	public static void appendLines(File file, String[] lines) throws IOException
	{
		if( file == null )
			throw new IOException("File is null.");
		writeLines(new FileOutputStream(file, true), lines);
	}

}

Page

import java.util.List;

/**
 * 分页
 * @param <T>
 */
public class Page<T> {

    // 结果集
    private List<T> rows;

    // 查询记录数
    private int total;

    // 每页多少条数据
    private int pageSize = 10;

    // 第几页
    private int pageNo = 1;

    // 跳过几条数
    private int skip = 0;

    /**
     * 总页数
     * @return
     */
    public int getTotalPages() {

        return (total + pageSize - 1) / pageSize;
    }

    public List<T> getRows() {
        return rows;
    }

    public void setRows(List<T> rows) {
        this.rows = rows;
    }

    public int getTotal() {
        return total;
    }

    public void setTotal(int total) {
        this.total = total;
    }

    public int getPageSize() {

        return pageSize;
    }

    public void setPageSize(int pageSize) {

        this.pageSize = pageSize;
    }

    public int getSkip() {

        skip = (pageNo - 1) * pageSize;
        return skip;
    }

    public void setSkip(int skip) {

        this.skip = skip;
    }

    public int getPageNo() {

        return pageNo;
    }

    public void setPageNo(int pageNo) {
        // offset
        if (pageNo == 0) {
            this.pageNo = pageNo+1;
        } else {
            this.pageNo = pageNo;
        }

    }
}

ResultMsg

import java.io.Serializable;

public class ResultMsg<T> implements Serializable {

	private static final long serialVersionUID = 2635002588308355785L;

	private int status;
	private String msg;
	private T data;

	public ResultMsg() {
	}
	
	public ResultMsg(int status) {
		this.status = status;
	}

	public ResultMsg(int status, String msg) {
		this.status = status;
		this.msg = msg;
	}
	
	public ResultMsg(int status, T data) {
		this.status = status;
		this.data = data;
	}

	public ResultMsg(int status, String msg, T data) {
		this.status = status;
		this.msg = msg;
		this.data = data;
	}

	public int getStatus() {
		return status;
	}

	public void setStatus(int status) {
		this.status = status;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}

}

DateUtils

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 日期工具类
 * @author asf
 */
public class DateUtils {

    /**
     * 根据给定的日期格式将日期字符串转化成对应的日期格式
     * @param str 日期字符串
     * @param format  日期格式
     * @return 转化后的日期类型
     */
    public static Date getDate(String str, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            if(str == null || "".equals(str)) {
                return new Date();
            }
            return sdf.parse(str);
        } catch (ParseException e) {

        }
        return new Date();
    }

    /**
     * 根据给定的日期格式将日期字符串转化成对应的日期格式字符串
     * @param str 日期字符串
     * @param pattern 日期格式
     * @return 转化后的日期类型
     */
    public static String getStrDate(String str, String pattern) {
        //针对数据库中存在的这种格式日期字符串进行处理
        //2019-11-21 15:52:55.0
        str = (str.contains(".0")) ? str.substring(0, str.indexOf(".0")): str;
        //针对传入日期字符串和日期格式不一致数据进行处理
        str = (str.trim().length() > pattern.trim().length()) ? str.substring(0, pattern.length()) : str;
        LocalDate localDate = LocalDate.parse(str, DateTimeFormatter.ofPattern(pattern));

        return localDate.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 根据给定的日期格式将日期转化成对应的日期格式字符串
     * @param dateTime 日期
     * @param pattern 日期格式
     * @return 转化后的日期类型
     */
    public static String getStrDate(Date dateTime, String pattern) {

        LocalDate localDate = dateTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

        return localDate.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 根据给定的日期格式将当前日期转化成对应的日期格式字符串
     * @param pattern 日期格式
     * @return 转化后的日期类型
     */
    public static String getStrDate(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now();
        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     *
     * @param str
     * @param sdf
     * @return
     */
    public static Date getDate(String str, SimpleDateFormat sdf) {
        try {
            if(str == null || "".equals(str)) {
                return new Date();
            }
            return sdf.parse(str);
        } catch (ParseException e) {

        }
        return new Date();
    }

    /**
     * 根据字符串格式日期获取LocalDateTime对象
     * @param str
     * @return
     */
    public static LocalDateTime getLocalDateTime(String str) throws ParseException {
        LocalDateTime localDateTime = null;
        Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(str);
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime;
    }

    /**
     * 根据字符串格式日期和日期格式获取LocalDateTime对象
     * @param str
     * @param pattern
     * @return
     */
    public static LocalDateTime getLocalDateTime(String str, String pattern) throws ParseException {
        LocalDateTime localDateTime = null;
        Date date = new SimpleDateFormat(pattern).parse(str);
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime;
    }
}

DownloadFileUtils

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 文件下载工具类
 *
 */
public class DownloadFileUtils {


    /**
     * 把byte数组数据转换成文件
     * @param response
     * @param bytes    上传文件转换的字节数组
     * @param fileName 上传文件的文件名  格式 文件名.文件类型 ,如 abc.txt
     * @throws IOException
     */
    public static void getFileByBytes(HttpServletResponse response, byte[] bytes, String fileName) throws IOException {
        //此处需要设置ISO8859-1,application/octet-stream为未知文件类型时使用
        response.setContentType("application/octet-stream;charset=ISO8859-1");
        BufferedOutputStream output = null;
        //将文件以文件流的方式输出
        output = new BufferedOutputStream(response.getOutputStream());
        String fileNameDown = new String(fileName.getBytes(), "ISO8859-1");
        //fileNameDown上面得到的文件名
        response.setHeader("Content-Disposition", "attachment;filename=" +
                fileNameDown);
        output.write(bytes);
        response.flushBuffer();
        output.flush();
        output.close();
    }

    /**
     * 把byte数组数据转换成文件
     * @param bytes    上传文件转换的字节数组
     * @param fileName 上传文件的文件名  格式 文件名.文件类型 ,如 abc.txt
     * @throws IOException
     */
    public static void getFileByBytes(byte[] bytes, String fileName) throws IOException {
        HttpServletResponse response = WebUtils.getResponse();
        //此处需要设置ISO8859-1,application/octet-stream为未知文件类型时使用
        response.setContentType("application/octet-stream;charset=ISO8859-1");
        BufferedOutputStream output = null;
        //将文件以文件流的方式输出
        output = new BufferedOutputStream(response.getOutputStream());
        String fileNameDown = new String(fileName.getBytes(), "ISO8859-1");
        //fileNameDown上面得到的文件名
        response.setHeader("Content-Disposition", "attachment;filename=" +
                fileNameDown);
        output.write(bytes);
        output.flush();
        output.close();
        response.flushBuffer();
    }

    /**
     * 把文件流转换成文件
     * @param in  文件流
     * @param fileName  上传文件的文件名  格式 文件名.文件类型 ,如 abc.txt
     * @throws IOException
     */
    public static void getFileByInputStream(InputStream in, String fileName) throws IOException {
        getFileByBytes(IoUtil.toByteArray(in), fileName);
    }

    /**
     * 文件下载
     * @param bytes    上传文件转换的字节数组
     * @param fileName 上传文件的文件名  格式 文件名.文件类型 ,如 abc.txt
     * @return
     */
    public static ResponseEntity<byte[]> getResponseEntityByByte(byte[] bytes, String fileName){
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentDispositionFormData("attachment", fileName);
        //设置MIME类型
        httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        return new ResponseEntity<byte[]>(bytes, httpHeaders, HttpStatus.OK);
    }

    /**
     * 文件下载
     * @param in   文件流
     * @param fileName  上传文件的文件名  格式 文件名.文件类型 ,如 abc.txt
     * @return
     * @throws IOException
     */
    public static ResponseEntity<byte[]> getResponseEntityByByte(InputStream in, String fileName) throws IOException {
        return getResponseEntityByByte(IoUtil.toByteArray(in), fileName);
    }


    /**
     *
     * @param file
     * @param fileName
     * @throws Exception
     */
    public static void compressFileWithZip(File file,String fileName) throws Exception {
//        HttpServletResponse response = WebUtils.getResponse();
        //定义压缩文件的名称
        File zipFile = new File(fileName);
        //定义输入文件流
        InputStream input = new FileInputStream(file);
        //定义压缩输出流
        ZipOutputStream zipOut = null;
        //实例化压缩输出流,并制定压缩文件的输出路径 就是D盘下,名字叫 demo.zip
        zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
        zipOut.putNextEntry(new ZipEntry(file.getName()));
        //设置注释
//        zipOut.setComment("www.demo.com");
        int temp = 0;
        while((temp = input.read()) != -1) {
            zipOut.write(temp);
        }
        input.close();
        zipOut.close();
    }
}

WebUtils

import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


/**
 * 扩展 <code>org.springframework.web.util.WebUtils</code>
 * 
 * @since 1.0
 */
public abstract class WebUtils extends org.springframework.web.util.WebUtils {
	
	
	public static HttpServletRequest getRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}
	
	/**
	 * spring版本较低,不支持该方法
	 * @return
	 */
	public static HttpServletResponse getResponse() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
	}
	
	
	public static HttpSession getSession() {
		return getRequest().getSession();
	}
	
	
	public static ServletContext getServletContext() {
		return ContextLoader.getCurrentWebApplicationContext().getServletContext();
	}
	
	
	public static String getContextPath() {
		return getRequest().getContextPath();
	}
	
	
	public static String getCookieValue(HttpServletRequest request, String key) {
		Cookie cookie = getCookie(request, key);
		if(cookie != null) {
			return cookie.getValue();
		}
		return "";
	}
	
	public static String getSessionIdWithCookie(HttpServletRequest request, String cookieKey) {
		String sessionId = request.getSession().getId();
		Cookie cookie = getCookie(request, cookieKey);
		if(cookie != null) {
			sessionId = cookie.getValue();
		}
		return sessionId;
	}

	/**
	 * 获取当前请求的ip地址
	 * @param request
	 * @return
	 */
	public static String getIpAddr(HttpServletRequest request){
		String ip = request.getHeader("X-Real-IP");
		if(!StringUtils.isBlank(ip)&&!"unknown".equalsIgnoreCase(ip))
		{
			return ip;
		}
		ip = request.getHeader("X-Forwarded-For");
		if(!StringUtils.isBlank(ip)&& !"unknown".equalsIgnoreCase(ip))
		{
			int index = ip.indexOf(',');
			if(index != -1){
				return ip.substring(0, index);
			}else{
				return ip;
			}
		}
		ip = request.getHeader("Proxy-Client-IP");
		if(!StringUtils.isBlank(ip)&&!"unknown".equalsIgnoreCase(ip))
		{
			return ip;
		}
		ip = request.getHeader("WL-Proxy-Client-IP");
		if(!StringUtils.isBlank(ip)&&!"unknown".equalsIgnoreCase(ip))
		{
			return ip;
		}
		ip = request.getRemoteAddr();
		if("0:0:0:0:0:0:0:1".equals(ip)){
			ip = "127.0.0.1";
		}
		return ip;
	}
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值