//工具类
package com.xulon.springBootShiro.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 将图片缩略片工具类
*/
public class ImageThumbUtil {
/**
* 按照尺寸缩放图片
*/
public static void resize(File originalFile, FileOutputStream fos, int w, int h) throws IOException {
Image image = ImageIO.read(originalFile);
resize(image, fos, w, h);
}
/**
* 按照尺寸缩放图片
*
* @param fis 源图片文件流
* @param fos 缩略图文件流
* @param w int 宽度
* @param h int 高度
* @throws IOException
*/
public static void resize(FileInputStream fis, FileOutputStream fos, int w, int h) throws IOException {
Image img = ImageIO.read(fis);
resize(img, fos, w, h);
}
/**
* 按照固定的比例缩放图片
*
* @param originalFile 源图片文件
* @param fos 缩略图文件流
* @param t double 缩放比例
* @throws IOException
*/
public static void resize(File originalFile, FileOutputStream fos, double t) throws IOException {
FileInputStream fis = new FileInputStream(originalFile);
resize(fis, fos, t);
}
/**
* 按照固定的比例缩放图片
*
* @param fis 源图片文件流
* @param fos 缩略图文件流
* @param t double 缩放比例
* @throws IOException
*/
public static void resize(FileInputStream fis, FileOutputStream fos, double t) throws IOException {
Image image = ImageIO.read(fis);
int w = (int) (image.getWidth(null) * t);
int h = (int) (image.getHeight(null) * t);
resize(image, fos, w, h);
}
/**
* 以宽度为基准,等比例放缩图片
*
* @param originalFile 源图片文件
* @param fos 缩略图文件流
* @param w int 新宽度
* @throws IOException
*/
public static void resizeByWidth(File originalFile, FileOutputStream fos, int w) throws IOException {
FileInputStream fis = new FileInputStream(originalFile);
resizeByWidth(fis, fos, w);
}
/**
* 以宽度为基准,等比例放缩图片
*
* @param fis 源图片文件流
* @param fos 缩略图文件流
* @param w int 新宽度
* @throws IOException
*/
public static void resizeByWidth(FileInputStream fis, FileOutputStream fos, int w) throws IOException {
Image image = ImageIO.read(fis);
int width = image.getWidth(null);
int height = image.getHeight(null);
int h = height * w / width;
resize(image, fos, w, h);
}
/**
* 以高度为基准,等比例缩放图片
*
* @param originalFile 源图片文件
* @param fos 缩略图文件流
* @param h int 新高度
* @throws IOException
*/
public static void resizeByHeight(File originalFile, FileOutputStream fos, int h) throws IOException {
FileInputStream fis = new FileInputStream(originalFile);
resizeByHeight(fis, fos, h);
}
/**
* 以高度为基准,等比例缩放图片
*
* @param fis 源图片文件流
* @param fos 缩略图文件流
* @param h int 新高度
* @throws IOException
*/
public static void resizeByHeight(FileInputStream fis, FileOutputStream fos, int h) throws IOException {
Image image = ImageIO.read(fis);
int width = image.getWidth(null);
int height = image.getHeight(null);
int w = width * h / height;
resize(image, fos, w, h);
}
/**
* 按照最大高度限制,生成最大的等比例缩略图
*
* @param originalFile 源图片文件
* @param fos 缩略图文件流
* @param w int 最大宽度
* @param h int 最大高度
* @throws IOException
*/
public static void resizeFix(File originalFile, FileOutputStream fos, int w, int h) throws IOException {
Image img = ImageIO.read(originalFile);
int width = img.getWidth(null);
int height = img.getHeight(null);
if (width / height > w / h) {
resizeByWidth(originalFile, fos, w);
} else {
resizeByHeight(originalFile, fos, h);
}
}
/**
* 按照尺寸缩放图片
*
* @param image 源图片
* @param fos 缩略图文件流
* @param w int 新宽度
* @param h int 新高度
* @throws IOException
*/
public static void resize(Image image, FileOutputStream fos, int w, int h) throws IOException {
try {
BufferedImage _image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
// 绘制缩小后的图
_image.getGraphics().drawImage(image, 0, 0, w, h, null);
//输出
ImageIO.write(_image, "jpeg", fos);
fos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
try {
String fileName = "C:/test.png";
fileName = "C:/test001.png";
File file = new File(fileName);
FileOutputStream fos = new FileOutputStream(new File(fileName + "_s.jpg"));
// resizeFix(file, fos, 300, 200);
// resizeByWidth(file, fos, 300);
// resizeByHeight(file, fos, 600);
// resize(file, fos, 200, 300);
resize(file, fos, 0.6);
// resizeByHeight(file, fos, 100);
} catch (IOException e) {
e.printStackTrace();
}
}
}
//下载接口
package com.xulon.springBootShiro.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import com.xulon.springBootShiro.utils.ImageThumbUtil;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
@RestController
@RequestMapping("/upload")
@Api(tags = "文件管理")
public class UploadController {
public static Logger log = LoggerFactory.getLogger(UploadController.class);
private static final int BUFFER = 1024 * 8;//自定义缓存区大小,一次读取磁盘文件到内存,根据实际情况优化调整
private static final String MODE = "r";//RandomAccessFile工作模式,此处设置只读即可
/**
*, 文件下载
*
* @param request
* @param response
* @param id 原文件id
* @param w 缩略图宽(px)
* @param h 缩略图高(px)
* @throws IOException
*/
@GetMapping("/downloadFile")
@ApiOperation(value = "文件下载", notes = "文件下载")
public void downloadFile(HttpServletRequest request, HttpServletResponse response,
@RequestParam(required = false) Integer w,
@RequestParam(required = false) Integer h)
throws IOException {
//被下载的文件在服务器中的路径
String filePath = "D:/zTmpDown/downloadFile.jpg";
//被下载文件的名称
String fileName = "downloadFile";
File file = new File(filePath);
if(file.exists()){
//没有尺寸下载原图
if (w == null || h == null) {
download(request, response, filePath, fileName);
//下载缩略图
} else {
downloadThumb(response, filePath, fileName, w, h);
}
}else{
log.error("磁盘上找不到的文件");
}
}
/**
* ,文件下载,支持普通下载,断点继续下载,断点区间下载
*
* @param request 请求
* @param response 响应
* @param sourceFile 文件路径
* @param fileName 文件名称
*/
private void download(HttpServletRequest request, HttpServletResponse response, String sourceFile, String fileName) {
response.reset();
File file = new File(sourceFile);
long fileLength = file.length();
try {
RandomAccessFile raf = new RandomAccessFile(file, MODE);
ServletOutputStream sos = response.getOutputStream();
String rangeBytes = null;
//RangeSwitchEnum rangeSwitch = RangeSwitchEnum.ORDINARY;
String rangeSwitch = "";
long pastLength = 0;
long toLength;
long contentLength;
if (null != request.getHeader("Range")) {
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
rangeBytes = request.getHeader("Range").replaceAll("bytes=", "");
if (rangeBytes.indexOf('-') == rangeBytes.length() - 1) {
rangeSwitch = "BEGIN";
rangeBytes = rangeBytes.substring(0, rangeBytes.indexOf("-")).trim();
pastLength = Long.parseLong(rangeBytes);
contentLength = fileLength - pastLength;
} else {
rangeSwitch = "BLOCK";
pastLength = Long.parseLong(rangeBytes.substring(0, rangeBytes.indexOf("-")).trim());
toLength = Long.parseLong(rangeBytes.substring(rangeBytes.indexOf("-") + 1).trim());
contentLength = toLength - pastLength + 1;
}
} else {
contentLength = fileLength;
}
response = setResponse(response, contentLength, fileName);
switch (rangeSwitch) {
case "BEGIN": {
String contentRange = "bytes " + pastLength + "-" + (fileLength - 1) + "/" + fileLength;
response.setHeader("Content-Range", contentRange);
break;
}
case "BLOCK": {
String contentRange = "bytes " + rangeBytes + "/" + fileLength;
response.setHeader("Content-Range", contentRange);
break;
}
default: {
break;
}
}
inputStreamToOutputStream(raf, sos, pastLength, contentLength);
} catch (Exception e) {
log.error("文件下载发生错误!原因:" + e.getMessage());
}
}
/**
*, 缩略图文件下载
*, 实时原图转化缩略图返回数据较慢,创建临时文件夹存放缩略图可以增加图片传输效率
*
* @param response 响应
* @param sourceFile 文件路径
* @param fileName 文件名称
* @param w 图片宽
* @param h 图片高
*/
/**
* .从缩略图目录下载缩略图,没有重新生成并存储在目录下,
*/
private void downloadThumb(HttpServletResponse response, String filePath, String fileName, int w, int h) {
response.reset();
try {
File file = new File(filePath);
String thumbFileName = w + "x" + h + "_" + fileName;
String thumFilePath ="D:/zTmpDown/tmp/"+thumbFileName;
File thumbFile = new File(thumFilePath);
ByteArrayOutputStream bos =null;
if (thumbFile.exists()) {
//存在
response = setResponse(response, thumbFile.length(), thumbFileName);
bos = new ByteArrayOutputStream();
InputStream thumbFis = new FileInputStream(thumbFile);
byte[] b = new byte[1024];
int n;
while ((n = thumbFis.read(b)) != -1) {
bos.write(b, 0, n);
}
thumbFis.close();
bos.close();
}else {
FileOutputStream thumbFos = new FileOutputStream(thumbFile);
ImageThumbUtil.resize(file, thumbFos, w, h);
response = setResponse(response, thumbFile.length(), thumbFileName);
bos = new ByteArrayOutputStream();
InputStream thumbFis = new FileInputStream(thumbFile);
byte[] b = new byte[1024];
int n;
while ((n = thumbFis.read(b)) != -1) {
bos.write(b, 0, n);
}
thumbFis.close();
bos.close();
thumbFos.close();
}
OutputStream os = response.getOutputStream();
try {
//输出文件到客户端
if (os != null) {
os.write(bos.toByteArray());
}
} catch (Exception e) {
} finally {
if (os != null) {
os.flush();
os.close();
}
}
} catch (Exception e) {
log.error("文件下载发生错误!原因:" + e.getMessage());
}
}
/**
* ,设置响应对象信息
*
* @param response 响应对象
* @param contentLength 需要下载的文件长度
* @param fileName 文件名称
* @return 响应对象
* @throws Exception 抛出异常
*/
private HttpServletResponse setResponse(HttpServletResponse response, Long contentLength, String fileName) throws Exception {
//告示浏览器文件的打开方式是下载
//response.setContentType("application/x-download");
//response.setHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("UTF-8"), "ISO8859-1"));
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Content-Length", String.valueOf(contentLength));
return response;
}
/**
* ,从输入流中读取内容写入到输出流中
*
* @param raf 随机读取流
* @param sos 输出流
* @param pastLength 开始读取位置
* @param contentLength 读取的长度
*/
private void inputStreamToOutputStream(RandomAccessFile raf, ServletOutputStream sos, long pastLength, long contentLength) {
try {
if (pastLength != 0) {
raf.seek(pastLength);
}
byte[] buffer = new byte[BUFFER];
int length;
int readLength = 0;
while (readLength <= contentLength - BUFFER) {
length = raf.read(buffer, 0, BUFFER);
sos.write(buffer, 0, length);
readLength += length;
}
if (readLength < contentLength) {
length = raf.read(buffer, 0, (int) (contentLength - readLength));
sos.write(buffer, 0, length);
}
} catch (IOException e) {
log.info("文件下载时发生错误!无需担心,可能是客户端取消了下载:" + e.getMessage());
} finally {
if (sos != null) {
try {
sos.close();
} catch (IOException e) {
log.error("文件下载关闭输出流发生错误!原因:" + e.getMessage());
}
}
if (raf != null) {
try {
raf.close();
} catch (IOException e) {
log.error("文件下载关闭输入流发生错误!原因:" + e.getMessage());
}
}
}
}
}