JAVA 七月 25, 2022

2022学线暑假实训:山大迷踪图片服务

文章字数 1.1k 阅读约需 8 mins 阅读次数 1000000

记录第一次做图片服务后端

后端架构为:SpringBoot + Jpa + MySQL + JWT

本文同步在我的博客SPIN 自旋

需求

山大迷踪中关于图片的需求有:用户头像、发布迷踪帖(含照片)、发布匹配帖(含照片)、积分商城初始化(商品图片)。

分析

分析之后得出,后端应实现如下功能:

  1. 上传图片

  2. 保存图片

  3. 图片回传

  4. 删除废弃的头像、未过审帖子的照片、匹配成功后两帖子的照片

代码实现(以用户头像为例)

上传图片

采用formdata格式,直接上传图片文件,在后端使用MultipartFile类来接收。

Controller代码如下:

@PutMapping("/changeavatar")
public Result changeAvatar(MultipartFile avatar, HttpServletRequest request) {
    String token = request.getHeader("token");//从请求头中拿到token
    User user = userService.getUserByToken(token);//通过token来拿到用户实体
    userService.changeAvatar(user,avatar);// 修改该用户的头像
    return Result.success(JwtUtil.refreshToken(token));//返回成功码和新的token
}

其中,UserService.changeAvatar方法的实现如下:

@Override
public void changeAvatar(User user, MultipartFile avatar) {
    String avatarPath = ImgUtil.uploadAvatar(avatar);//保存图片到服务器,后面会贴出这个方法的代码
    if(avatarPath!=null&&user.getAvatar()!=null)ImgUtil.deleteImg(user.getAvatar());//存在旧头像则删除
    user.setAvatar(avatarPath);//保存用户头像url
    modifyUser(user);//更新用户
}

保存图片到服务器

上面我们已经拿到了图片的MutipartFile对象,现在我们把这个对象写成文件,保存在服务器的本地目录下。

这个过程,就是上文中说到的ImgUtil.uploadAvatar方法,代码如下:

package misstrace.Util;

import net.coobird.thumbnailator.Thumbnails;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

public class ImgUtil {

    //    定义头像存储地址 
    private static final String AVATAR_PATH = "/project/misstrace/tomcat8port8080/webapps/avatar/";
    //    定义访问头像的路径根部 http
    private static final String AVATAR_LOAD_PATH = "http://xxx.xxx.xxx/misstrace/avatar/";

    //将MultipartFile压缩保存
    public static String uploadAvatar(MultipartFile avatar) {
        //获得上传文件的名称
        String rawFileName = avatar.getOriginalFilename();
        //生成随机uuid,连接到原文件名前面,防止重名
        String uuid = UUID.randomUUID().toString().replace("-","");
        String newFileName = uuid+"-"+rawFileName;
        //压缩图片,并保存在上述路径
        Boolean flag = zipAvatar(avatar,AVATAR_PATH+newFileName);
        if(!flag)return null;
        return AVATAR_LOAD_PATH+newFileName;
    }
    
    // 压缩图片并保存在该目录下
    public static Boolean zipAvatar(MultipartFile img,String path) {
        try {
            //先压缩并保存图片
            Thumbnails.of(img.getInputStream()).size(128,128)  //压缩尺寸 范围(0.00--1.00)
                    .outputQuality(0.4f)  //压缩质量 范围(0.00--1.00)
                    .toFile(path); //输出路径
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}

上面的注释也说的很清楚了,我使用Thumbnails压缩了图片(这样能加速后续的“图片回传”功能,减轻服务器压力)

Thumbnails的依赖如下(放入pom.xml的dependencies标签中):

<!--图片处理thumbnailator-->
<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.17</version>
</dependency>

图片回传

在保存图片的时候,我传回的是带有图片名的url,这个url将一路传到前端手里,然后由前端来请求加载这个图片。

那么如何让前端通过url就能访问头像文件呢?

我这里采用的是tomcat,广播出去静态资源(可恶的华为云,安全组默认关掉了所有端口。。)。

后面其实还是使用nginx做了转发,这样能不暴露进程的端口。

再后来,就是研究了半天域名和https(ssl证书)的问题,虽然域名解析和https都能用,但考虑到我的域名只有半年期限了,还是继续使用原始的服务器ip了。

删除废弃的图片

直接上代码(在ImgUtil类中):

//通过url路径删除图片
public static Boolean deleteImg(String imgLoadPath) {
    boolean flag = false;
    String filePath = "/project/misstrace/tomcat8port8080/webapps/"+imgLoadPath.substring(33);
    //根据路径创建文件对象
    File file = new File(filePath);
    //路径是个文件且不为空时删除文件
    if(file.isFile()&&file.exists()){
        flag = file.delete();
    }
    //删除失败时,返回false
    return flag;
}

总结

总体来说,这部分服务的实现过程还是很愉快的,一个从0到1的过程,”接口生效“的正向反馈让我有些上头。

然而在上手的时候,我还是意识到对异常处理的陌生。


上一篇 :  
下一篇 :  
0%