项目实训11

项目实训11

1. 背景

由于项目中有需要上传图片的需求,所以在此记录一下上传图片的流程和做法

2. 做法

本需求的流程是,前端向后端上传图片,后端接受图片,并返回图片的打分。

@UserLoginToken
    @ResponseBody
    @PostMapping("/upload")
    public Result uploadPicture(@RequestParam("file") MultipartFile file,
                                int id,
                                HttpServletRequest request) throws IOException, InterruptedException
    {

        if (file == null)
            throw new CustomException("图片文件为空");

        String openid = openidUtils.getOpenidFromRequest(request);

        // 根据源图片类型创建响应的文件夹
        String path = base_path;
        path += Integer.toString(id);
        path += "/";
        //将文件保存到服务器指定位置
        try
        {
            //获取文件在服务器的储存位置
            File filePath = new File(path);
            log.debug("文件的保存路径" + path);
            if (!filePath.exists() && !filePath.isDirectory())
            {
                log.debug("目录不存在,创建目录" + filePath);
                filePath.mkdir();
            }
            Upload uploadImage = new Upload();

            //获取原始文件名称(包括格式)
            String originalFileName = file.getOriginalFilename();

            //获取文件类型,以最后一个‘.’为标识
            String type = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);


            // 以用户的openid对图片进行命名
            String name = openid;

            // 设置文件新名称:用户的openid
            Date d = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            String date = sdf.format(d);
            String fileName = date + name + "." + type;
            // 在指定路径下创建文件
            File targetFile = new File(path, fileName);
            file.transferTo(targetFile);
            System.out.println("上传成功");


            // 保存upload的信息到数据库
            uploadImage.setName(id);
            uploadImage.setAddress(path + fileName);
            uploadImage.setTime(d);
            uploadImage.setOpenid(openid);

            // TODO: 这里还有一个需要做的工作是调用python脚本获取评分 (根据图片的本地地址) 最后将评分返回给前端,也得保存至数据库
            // 由于获取到的数据为string类型,所以这边先转为double
            // 然后得分 *100
            // 然后再转化为整数
            String result = this.getScore(path + fileName, id);
            double res = Double.parseDouble(result) * 100;
            int score = (int) res;

            uploadImage.setScore(score);

            // 更新source表相应图片的描绘次数
            sourceService.updateCountById(id);

            // 更新user表的总评分
            userService.updateUserScore(uploadImage.getScore(), openid);

            // 插入upload表信息
            uploadService.insertUpload(uploadImage);
            Map<String, Object> map = new HashMap<>();
            map.put("score", score);
            return ResultFactory.success().message("上传成功").data(map);
        } catch (Exception e)
        {
//            System.out.println("上传失败");
//            result.put("code",400);
            log.error("保存图片失败");
            e.printStackTrace();
            return ResultFactory.error().message("上传失败");
        }


    }

其中@UserLoginToken注解已经在前面的博客中有提到,是用来验证用户token的

其中的getOpenidFromRequest方法如下:由于经常要从请求的header中抽出openid,所以剥离出来了一个工具类的方法,主要作用就是从header的token字段中提取出用户的openid。

    public String getOpenidFromRequest(HttpServletRequest request)
    {

        String token = request.getHeader("token");// 从 http 请求头中取出 token
//        if(token == null)
//            throw new CustomException(ResultCodeEnum.NO_TOKEN);
        // 获取 token 中的 user openid
        String openid;
        try
        {
            openid = JWT.decode(token).getAudience().get(0);
            log.info(openid);
        } catch (JWTDecodeException j)
        {
            throw new RuntimeException("token解析出错");
        }
        return openid;

    }

之后将获取到的图片保存到服务器的某个位置,本项目是保存到了nginx的静态资源配置目录下面,便于后面拓展需求的时候需要返回上传上来的图片给用户,便可以直接返回在线地址。

方法的具体流程在代码的注释已经给的很详细了,就不再阐述了。

上传文件使用的是MultipartFile类。

下面看看MultipartFile工具类的源码

package org.springframework.web.multipart;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.FileCopyUtils;

public interface MultipartFile extends InputStreamSource {
//getName() 返回参数的名称
    String getName();
//获取源文件的昵称
    @Nullable
    String getOriginalFilename();
//getContentType() 返回文件的内容类型
    @Nullable
    String getContentType();
//isEmpty() 判断是否为空,或者上传的文件是否有内容
    boolean isEmpty();
//getSize() 返回文件大小 以字节为单位
    long getSize();
//getBytes() 将文件内容转化成一个byte[] 返回
    byte[] getBytes() throws IOException;
//getInputStream() 返回InputStream读取文件的内容
    InputStream getInputStream() throws IOException;

    default Resource getResource() {
        return new MultipartFileResource(this);
    }
//transferTo(File dest) 用来把 MultipartFile 转换换成 File
    void transferTo(File var1) throws IOException, IllegalStateException;

    default void transferTo(Path dest) throws IOException, IllegalStateException {
        FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest));
    }
}


1、“流”是一个抽象的概念,它是对输入输出设备的一种抽象理解,在java中,对数据的输入输出操作都是以“流”的方式进行的。

2、“流”具有方向性,输入流、输出流是相对的。当程序需要从数据源中读入数据的时候就会开启一个输入流,相反,写出数据到某个数据源目的地的时候也会开启一个输出流。

3、数据源可以是文件、内存或者网络等。

所以使用该工具类能够比较便捷地上传文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值