前后端分离项目—通用后台管理系统(Vue + SpringBoot)【五】

通用后台管理系统

该系统主要结合Element组件编辑前端,后端实现业务逻辑,组成一个简单的前后端分离项目。

该部分介绍调用讯飞星火大模型的图片识别API功能的实现

前言:讯飞开放平台提供了一些免费的api供学习使用,可以包装进该项目中。例如图像识别api,前端上传图片,调用讯飞的api,然后返回结果。

讯飞开放平台地址:https://www.xfyun.cn/

该项目使用图像识别中的物体识别api:http://tupapi.xfyun.cn/v1/currency

文档链接:https://www.xfyun.cn/doc/image/object-recg/API.html
文档中有调用示例,选择java语言,因为识别的类别有点多,可以将下载的详细对照表写进数据库中,然后取结果的时候进行sql查询

前端

页面效果

在卡片中设置了一个选择框,选择不同的模型;模型的不同,卡片的内容显示也不一样。(目前只做了星火大模型)
在这里插入图片描述 在这里插入图片描述
识别效果:点击上传->选择图片文件->上传完成展示图片信息->显示识别结果
因为星火模型的要求,上传的图片大小要小于800kb。
在这里插入图片描述

前端代码

页面部分

<template>
  <div>
    <!--左侧 -->
    <el-col :span="8" style="padding-right: 10px; padding-left: 50px">
      <el-card class="select-card">
        <span style="color: #1fb1ec">选择模型:</span>
        <!--选择模型框-->
        <div>
          <el-select v-model="value" placeholder="select your model" @change="selectChanged">
            <el-option
                v-for="item in options"
                :key="item.value"
                :label="item.label"
                :value="item.value">
            </el-option>
          </el-select>
        </div>
        <div id="recPicApi" style="display: none">
          <!--上传照片部分-->
          <div id="upPicId" style="padding-top: 30px">
            <span style="color: #1fb1ec">上传需要识别的图片:</span>
            <el-upload
                class="upload-demo"
                :action=uploadPath
                :file-list="fileList"
                :on-success="uploadSuccess"
                list-type="picture"
                style="padding-top: 10px">
              <el-button @click='uploadMethod' size="small" type="primary">点击上传</el-button>
              <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过800kb</div>
            </el-upload>
          </div>
          <!--显示结果部分-->
          <div id="resPicId" style="top: 50vh; position: absolute">
            <span style="color: #1fb1ec; margin-top: 50px">识别结果为:</span>
            <span class="pic-res">{
   
   { xunfeiRes }}</span>
          </div>
        </div>
      </el-card>
    </el-col>
    <!--右侧 -->
    <el-col :span="16" style="padding-right: 10px">
    </el-col>
  </div>
</template>

模型选择框

options: [{
    
    
        value: '选项1',
        label: 'ChatGPT'
      }, {
    
    
        value: '选项2',
        label: '星火大模型'
      }, {
    
    
        value: '选项3',
        label: '通义千问'
      }, {
    
    
        value: '选项4',
        label: '文心一言'
      }],

上传地址:uploadPath该参数写上传文件的接口地址

上传成功:上传完成的时候调用后端物体识别的接口

	uploadSuccess(response, file) {
    
    
      console.log(file)
      if (response.message === 'success') {
    
    
        this.picMessage.filename = file.name;
        console.log(file.name)
        recognizePic({
    
    params: {
    
    ...this.picMessage}}).then(({
     
     data}) => {
    
    
          console.log(data)
          this.xunfeiRes = data.data
        })
      }
    },

div盒和选择框中的值关联

	selectChanged(value) {
    
    
      console.log(value)
      if (value === '选项2') {
    
    
        document.querySelector("#recPicApi").style.display = 'block';
      } else {
    
    
        document.querySelector("#recPicApi").style.display = 'none';
      }
    }

后端部分
前端使用的后端接口:import {recognizePic} from '@/api'
上传图片:

当前项目中是将图片上传到linux服务器上,并通过配置nginx服务来建立文件服务器。当处于局域网时,nginx配置中暴露的文件夹路径可以访问,所以上传完成时,通过将文件地址写入数据库中,这样物体识别接口直接查询数据库取该文件路径即可。

	@PostMapping("/upload")
    public ResultHelper uploadFolder(MultipartFile file) {
    
    
        try {
    
    
            byte[] bytes = file.getBytes();
            String filename = file.getOriginalFilename();
            FTPUtil.sshSftp(bytes, filename);
            String filepath = visitPath + filename;
            pictureMapper.addPicture(filename, filepath);
            return ResultHelper.success("上传成功");
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return ResultHelper.fail("上传失败");
    }

识别图片:

前端上传完图片后,给识别接口提供一个文件名,这样通过文件名在数据库中找到可访问的图片路径。

 @GetMapping("/recognize")
    public ResultHelper recognizePic(@RequestParam(value = "filename", required = false) String filename) throws IOException {
    
    
        // 根据文件名查找数据库中该文件名对应的图片地址
        String filepath = recognizePic.getPicPath(filename);
        log.info("该图片地址为:" + filepath);
        // 根据科大讯飞接口识别图片
        Map<String, String> header = xfBuildHttpHeader.buildHttpHeader(filename);
        byte[] imageByteArray = FileUtil.read(filepath);
        String result = HttpUtil.doPost(URL.getContent(), header, imageByteArray);
        JSONObject jsonObject = JSON.parseObject(result);
        String labelId = jsonObject.getJSONObject("data").getJSONArray("fileList").getJSONObject(0).getString("label");
        String CHNName = recognizePic.searchCategoryByLabelId(Integer.parseInt(labelId));
        log.info("接口调用结果:" + result);
        log.info(filename + ",该图片预测结果为:" + CHNName);
        return ResultHelper.success(CHNName);
    }

http header方法,其中API_KEY、APPID从讯飞的开放平台获取。

 public Map<String, String> buildHttpHeader(String imageName) throws UnsupportedEncodingException {
    
    
        String curTime = System.currentTimeMillis() / 1000L + "";
        String param = "{\"image_name\":\"" + imageName + "\"}";
        String paramBase64 = new String(Base64.encodeBase64(param.getBytes("UTF-8")));
        String checkSum = DigestUtils.md5Hex(API_KEY.getContent() + curTime + paramBase64);
        Map<String, String> header = new HashMap<String, String>();
        header.put("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
        header.put("X-Param", paramBase64);
        header.put("X-CurTime", curTime);
        header.put("X-CheckSum", checkSum);
        header.put("X-Appid", APPID.getContent());
        return header;
    }

FileUtil.read()方法中在读取本地路径时可以用讯飞提供的代码,若是读取url路径的文件,需要改一下:

public static byte[] read(String filePath) throws IOException {
    
    
        URL url = new URL(filePath);
        InputStream in =new BufferedInputStream(url.openStream());
//        InputStream in = Files.newInputStream(Paths.get(filePath));  // 原代码
        byte[] data = inputStream2ByteArray(in);
        in.close();
        return data;
    }

猜你喜欢

转载自blog.csdn.net/weixin_55488173/article/details/134603227