java实现小程序上传图片至云服务器(一条龙服务)

上传图片的一系列相关操作:

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.net/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.com/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.apache.commons.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.net/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.com:443/flowercity-0.0.1-SNAPSHOT/uploadImages/" + pictureName;
}
        return allpath;
    }

参考文章:
https://blog.csdn.net/qq_38765867/article/details/106383150

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值