上传图片的一系列相关操作:
1.对上传的图片进行标准化处理(微信的security.imgSecCheck接口对图片大小及尺寸要求严格)
该接口对校验的图片有要求,一是大小不能超过1M,二是图片尺寸不超过750px * 1334px。
2.对接小程序security.imgSecCheck接口,过滤恶意图片
图片智能鉴黄:涉及拍照的工具类应用(如美拍,识图类应用)用户拍照上传检测;电商类商品上架图片检测;媒体类用户文章里的图片检测等;
敏感人脸识别:用户头像;媒体类用户文章里的图片检测;社交类用户上传的图片检测等。
3.保存图片至服务器,并将用UUID随机命名的图片名存入数据库
4.拼接图片路径,从服务器获取图片。
详细代码
1.添加依赖
<!-- 图片处理工具类 -->
<dependency>
<groupId>com.rjp</groupId>
<artifactId>ImageUtils</artifactId>
<version>1.0.0</version>
</dependency>
<!--后台调用 http 请求-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<!--压缩图片-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
2.添加图片工具类(无需改动)
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
/**
* 图片处理工具类:<br>
* 功能:缩放图像、切割图像、图像类型转换、彩色转黑白、文字水印、图片水印等
* @author Administrator
*/
public class ImageUtils {
/**
* 几种常见的图片格式
*/
public static String IMAGE_TYPE_GIF = "gif";// 图形交换格式
public static String IMAGE_TYPE_JPG = "jpg";// 联合照片专家组
public static String IMAGE_TYPE_JPEG = "jpeg";// 联合照片专家组
public static String IMAGE_TYPE_BMP = "bmp";// 英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式
public static String IMAGE_TYPE_PNG = "png";// 可移植网络图形
public static String IMAGE_TYPE_PSD = "psd";// Photoshop的专用格式Photoshop
/**
* 程序入口:用于测试
* @param args
*/
public static void main(String[] args) {
// -图像类型转换:
ImageUtils.convert("D:/IMG_20180811_222034.png", "jpg", "D:/test.jpg");//测试OK
}
/**
* 图像类型转换:GIF->JPG、GIF->PNG、PNG->JPG、PNG->GIF(X)、BMP->PNG
* @param srcImageFile 源图像地址
* @param formatName 包含格式非正式名称的 String:如JPG、JPEG、GIF等
* @param destImageFile 目标图像地址
*/
public final static void convert(String srcImageFile, String formatName, String destImageFile) {
try {
File f = new File(srcImageFile);
f.canRead();
f.canWrite();
BufferedImage src = ImageIO.read(f);
ImageIO.write(src, formatName, new File(destImageFile));
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.标准化—恶意图片过滤—保存图片并上传图片名
下面这些都写在一个controller类里面就OK。
note:
关于涉及到的参数openid以及token号等,如果不太了解的怎么获取可以查看这篇文章–>https://blog.csdn/ZLZQ_Yuan/article/details/107624325
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springboot.wechatcity.utill.ImageUtils;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.io.*;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.util.*;
import net.coobird.thumbnailator.Thumbnails;
/**
* 主操作函数:标准化-恶意图片过滤-保存图片并上传图片名
* @param accessToken 用户访问小程序接口凭证
* @throws Exception
*/
@CrossOrigin(origins = {"*", "3600"}) //跨域注解,所有域名都可访问,且cookie的有效期为3600秒
@RequestMapping(value = "/checkSaveImg")
public Map<String, Object> checkImg(HttpServletRequest httpServletRequest, String accessToken) throws Exception {
Map<String, Object> resultMap = new HashMap<>();//存放返回信息
//HttpServletRequest不能直接取出文件数据,所以将其强制转换为MultipartHttpServletRequest
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) httpServletRequest;
MultipartFile multipartFile = multipartRequest.getFile("file");//file为前端上传的图片名
//1.压缩图片
InputStream inputStream = compressImage(multipartFile);
//2.过滤图片
String url = "https://api.weixin.qq/wxa/img_sec_check?access_token=" + accessToken;//微信开放接口链接
// 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的
HttpClient httpclient = HttpClients.createDefault();
//创建一个post请求
HttpPost request = new HttpPost(url);
//设置响应头 ( application/octet-stream:二进制流,不知道下载文件类型)
request.addHeader("Content-Type", "application/octet-stream");
try {
//创建一个byte数组,和输入的文件的大小一样
byte[] byt = new byte[inputStream.available()];
//从输入流中读取全部,并将其存储在缓冲区数组byt 中。
inputStream.read(byt);
//定制提交内容
request.setEntity(new ByteArrayEntity(byt, ContentType.create("image/jpg")));
// 由客户端执行(发送)请求,执行校验
HttpResponse response = httpclient.execute(request);
// 从响应模型中获取响应实体
HttpEntity entity = response.getEntity();
// 转成string,打印校验结果
String result = EntityUtils.toString(entity, "UTF-8");
System.out.println("checkImgResult:" + result);
//3.若图片合法,保存
if (result.contains("0")) {
resultMap = saveImg(multipartFile);
} else if (result.contains("87014")) {
resultMap.put("code", 87014);
resultMap.put("msg", "图片含敏感内容!");
} else {
resultMap.put("code", 444);
resultMap.put("msg", "其他错误!");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return resultMap;
}
ps:以下方法无需修改
/**
* 压缩标准化图片
* @param multipartFile 上传的图片实体
* @return
*/
public InputStream compressImage(MultipartFile multipartFile) {
//*************对不是jpg格式的图片转换成jpg格式***************
//获取文件名后缀,判断其格式
int begin = multipartFile.getOriginalFilename().lastIndexOf(".");
int last = multipartFile.getOriginalFilename().length();
//获得文件后缀名
String houzuiFileName = multipartFile.getOriginalFilename().substring(begin, last);
//创建临时文件
File tempFile = new File(multipartFile.getOriginalFilename());
//写入临时File文件 tempFile,将multipartFile转换成File
try {
//import org.apachemons.io.FileUtils;
FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), tempFile);
} catch (IOException e) {
e.printStackTrace();
}
//如果文件不是jpg格式,转换其格式
if (!"jpg".equalsIgnoreCase(houzuiFileName)) {
//ImageUtils是一个工具类,下面给出
//将png格式转换成jpg,输出到tempFile
ImageUtils.convert(multipartFile.getOriginalFilename(), "jpg", tempFile.getAbsolutePath());//测试OK
//*************对不是jpg格式的图片转换成jpg格式***************
}
try {
//压缩图片
BufferedImage bufferedImage = Thumbnails.of(tempFile)
.size(740, 1330)//指定压缩之后的图片尺寸
.outputQuality(0.8f)//图片压缩质量
.asBufferedImage();
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", os);
InputStream inputStream = new ByteArrayInputStream(os.toByteArray());
// System.out.println(inputStream);
return inputStream;
} catch (IOException e) {
e.printStackTrace();
} finally {
// 会在本地产生临时文件,用完后需要删除
if (tempFile.exists()) {
tempFile.delete();
}
}
return null;
}
ps:以下方法中关于项目路径,这篇里面详细讲了https://blog.csdn/ZLZQ_Yuan/article/details/107367371
/**
* 保存图片至服务器,并将随机命名的图片名存入数据库
* @param multipartFile
* @return
* @throws IOException
*/
public Map<String, Object> saveImg(MultipartFile multipartFile) throws IOException {
Map<String, Object> resultMap = new HashMap<>();//存放返回信息
//获取上传文件的扩展名,并判断是否在允许的文件类型范围内
String fileName = multipartFile.getOriginalFilename();
String ext = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());//
ext = ext.toLowerCase();//小写转换
List fileTypes = new ArrayList();//保存可上传的文件类型
fileTypes.add("jpg");
fileTypes.add("jpeg");
if (!fileTypes.contains(ext)) {
System.out.println("文件类型不允许.");
}
//用UUID重命名图片
String uuid = UUID.randomUUID().toString().replace("-", "");//UUID生成不重复的一串数字
String newName = uuid + "." + ext;
System.out.println("文件名:" + newName);
try {
//获取文件字节数组
byte[] bytes = multipartFile.getBytes();
String path1 = classesPath.substring(1, classesPath.indexOf("WEB-INF/classes"));//只保留WEB-INF/classes前面的,E:\eclipseM9/workspace/tree/
String path = path1 + "\\uploadImages\\";
System.out.println("文件上传路径:" + path);
//判断存放上传文件的目录是否存在(不存在则创建)
File files = new File(path);
if (!files.exists() && !files.isDirectory()) {
files.mkdirs();
}
//创建文件
File targetFile = new File(path, newName);
//写入指定文件夹
OutputStream out = new FileOutputStream(targetFile);
out.write(bytes);
System.out.println("图片保存至服务器成功~");
} catch (IOException e) {
e.printStackTrace();
System.out.println("图片保存至服务器失败!");
}
//上传图片名至数据库
subMessageService.uploadAllPictureNames(newName);
resultMap.put("code", 0);
resultMap.put("msg", "图片上传成功");
return resultMap;
}
}
4.后台拼接图片路径并返回给前端,前端通过img标签直接在线访问云服务器上的图片资源。
/**
* Todo 获取图片
* @return
*/
@CrossOrigin(origins = {"*", "3600"}) //跨域注解,所有域名都可访问,且cookie的有效期为3600秒
@RequestMapping(value = "/getPicture")
public String getPicture(HttpServletRequest request) {
//返回图片在线路径
String pictureName = infoService.getAllInfo().get(0).getPicture();//获取图片名
if (pictureName != null) {
String allpath = "https://www.flower:443/flowercity-0.0.1-SNAPSHOT/uploadImages/" + pictureName;
}
return allpath;
}
参考文章:
https://blog.csdn/qq_38765867/article/details/106383150
更多推荐
java实现小程序上传图片至云服务器(一条龙服务)
发布评论