IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 微信小程序基于vant和springboot实现附件上传和预览 -> 正文阅读

[移动开发]微信小程序基于vant和springboot实现附件上传和预览

前言

图片上传和预览在移动端应用非常广泛和频繁,vant组件库van-uploader组件已经帮我们实现了大部分功能,但是在系统中频繁使用还是有点麻烦,我们根据自身的业务系统重新封装了一下简化我们的开发。后端使用springboot集成jcifs实现文件管理微服务。

附件上传

附件预览

前端组件

组件介绍

前端只要在视图中使用组件,传入需要的参数即可

businessid业务id,用于把业务单号和附件关联
tmp_id临时业务id,在一开始业务单号未产生的时候和附件关联
name用于把不通类型的附件归类到不同的文件夹
businesstype用于区分同一个业务单号下不通类型的附件组
readonly判断组件是预览还是上传
<bdog-uploader-image      
	id="visit_uploader"
	businessid="{{id}}"
	tmp_id="{{tmp_id}}"
	name="customerVisit"
	businesstype="visit"
    readonly ="{{readonly}}"
/>  

组件js部分代码

const util = require('../../utils/util.js')
var request = require('../../utils/request.js')
var { config } = require('../../utils/config.js')
import Toast from '@vant/weapp/toast/toast';
const app = getApp();

Component({
  properties: {
    businessid: {
      type: String
    },
    tmp_id: {
        type: String
    },
    name: {
        type: String
    },
    businesstype: {
        type: String
    },
    readonly:{
        type:Boolean
    }
  },
  data: {
    fileList: [],
  },
  attached:function(){
    //this.getFileList()
  },
  methods: {
     afterRead(event) {
        Toast.loading({
            duration: 0, // 持续展示 toast
            forbidClick: true,
            message: "上传中"
        })
        var that = this
        const { file } = event.detail
        wx.uploadFile({
          url: config.baseUrl +'/MpAttachment/uploadFile', 
          filePath: file.url,
          name: 'file',
          header: {
            "Content-Type": "multipart/form-data",
            "id":that.data.businessid,
            "tmpId":that.data.tmp_id,
            "name":that.data.name,
            "businesstype":that.data.businesstype,
            "token":app.globalData.userInfo.token,
          },
          success(res) {
            const data = JSON.parse(res.data)
            if(data.code == 200){
                // 上传完成需要更新 fileList
                const { fileList = [] } = that.data;
                const url = config.baseUrl +'/MpAttachment/getImage?id=' + data.data.id
                fileList.push({ ...file, url: url, id: data.data.id })
                that.setData({ fileList })
                Toast.clear();
                Toast({ type: 'success',message: '上传成功',duration:500, })
            }else{
                Toast({ type: 'fail',message: '上传失败',duration:500, })
            }
          },
          fail:function(res){
            Toast({ type: 'fail',message: '上传失败',duration:500, })
          }
        });
      },
      delete(event) {
        Toast.loading({
            duration: 0, // 持续展示 toast
            forbidClick: true,
            message: "删除中"
        })
        var that = this
        var data = {}
        data['id'] = event.detail.file.id
        request.get('/MpAttachment/delete',data)
        .then(function (res) {
          if(res.code == 200){
            const { fileList } = that.data;
            const newFileList = fileList.filter((items) =>{
              return items.id != event.detail.file.id
            })
            that.setData({ fileList : newFileList, })
            Toast.clear();
            Toast({ type: 'success',message: '删除成功',duration:500, })
          }else{
            Toast({ type: 'fail',message: '删除失败',duration:500, })
          }
        }, function (error) {
            Toast({ type: 'fail',message: '删除失败',duration:500, })
        })
      },
      getFileList() {
        var that = this
        var data = {}
        data['businessid'] = that.data.businessid
        data['businesstype'] = that.data.businesstype
        request.get('/MpAttachment/getList',data)
        .then(function (res) {
          if(res.code == 200){
            const fileList = res.data;
            fileList.forEach(function(items){
                items.url = config.baseUrl + '/MpAttachment/getImage?id=' + items.id
                items.type = 'image'
            })
            that.setData({ fileList : fileList, })
          }else{
            Toast({ type: 'fail',message: '附件加载失败',duration:500, })
          }
        }, function (error) {
            Toast({ type: 'fail',message: '附件加载失败',duration:500, })
        })
      }
  }

})

组件视图部分代码

<van-cell title="" >
    <van-uploader
        slot="right-icon"
        file-list="{{ fileList }}"
        max-count="9"
        bind:after-read="afterRead"
        bind:delete="delete"  
        show-upload="{{ !readonly }}"
        deletable="{{ !readonly }}"
    />
</van-cell>
<van-toast id="van-toast" />

后端微服务

后端微服务

微服务总归包含了附件上传、删除、获取图片、获取列表、附件上传个服务

?微服务代码

package com.brickdog.controller;

@RestController
@RequestMapping("/MpAttachment")
@Api(tags = { Swagger2Config.TAG_MpAttachment })
public class MpAttachmentController implements ServletContextAware {

    protected HttpServletRequest request;
    protected HttpServletResponse response;
    protected HttpSession session;
    protected ServletContext servletContext;
    String FileConnect ="/";
    @Autowired
    protected UserService userService;
    @Autowired
    @Qualifier("dispJdbcTemplate")
    protected JdbcTemplate dispJdbcTemplate;
    @Autowired
    protected MpAttachmentService mpAttachmentService;

    @ApiOperation(value = "获取列表", notes = "")
    @GetMapping(value="/getList")
    public Result getList(@ApiParam(value = "businessid" , required=true ) @RequestParam String businessid,
                          @ApiParam(value = "businesstype" , required=false ) @RequestParam String businesstype) throws ParseException {
        List list =  mpAttachmentService.getViewList(businessid,businesstype);
        return Result.success(list,"成功!");
    }

    @CrossOrigin
    @ApiOperation(value = "附件上传", notes = "")
    @PostMapping("/uploadFile")
    public Result uploadFile(@RequestParam("file") MultipartFile file, @RequestHeader("name") String name, @RequestHeader String id, @RequestHeader String tmpId, @RequestHeader String businesstype) {
        if (file.isEmpty()) {
            return Result.failed("上传文件为空");
        }
        String uuid = UUID.randomUUID().toString();
        // 获取文件名
        String fileName = file.getOriginalFilename();
        String newFileName = uuid + "."+ fileName.split("\\.")[1];
        MpAttachment attachment = new MpAttachment();
        attachment.setBusinessid(id);
        attachment.setTmp_businessid(tmpId);
        attachment.setBusinesstype(businesstype);
        attachment.setFilename(fileName);
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyMMdd");
        String uploadPath = name + FileConnect + LocalDate.now().format(fmt);
        attachment.setFilepath(uploadPath + FileConnect + newFileName);

        try {
            SmbFileUtils.save(file.getBytes(),uploadPath,newFileName);
            attachment.setCreatetime(DateUtils.getNow());
            attachment.setId(UUID.randomUUID().toString());
            mpAttachmentService.add(attachment);
            return Result.success(mpAttachmentService.getView(attachment.getId()),"成功!");
        } catch (IOException e) {
            e.printStackTrace();
            return Result.failed("文件上传失败");
        }
    }


    @CrossOrigin
    @ApiOperation(value = "base64附件上传", notes = "")
    @PostMapping("/base64UploadFile")
    public Result base64UploadFile(@RequestBody String base64Image, @RequestHeader("fileName") String fileName, @RequestHeader("name") String name, @RequestHeader String id, @RequestHeader String tmpId, @RequestHeader String businesstype) throws UnsupportedEncodingException {
        String uuid = UUID.randomUUID().toString();
        base64Image = java.net.URLDecoder.decode(base64Image,"UTF-8");
        fileName = java.net.URLDecoder.decode(fileName,"UTF-8");
        id = java.net.URLDecoder.decode(id,"UTF-8");
        String newFileName = uuid + "."+ fileName.split("\\.")[1];
        MpAttachment attachment = new MpAttachment();
        attachment.setBusinessid(id);
        attachment.setTmp_businessid(tmpId);
        attachment.setBusinesstype(businesstype);
        attachment.setFilename(fileName);
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyMMdd");
        String uploadPath = name + FileConnect + LocalDate.now().format(fmt);
        attachment.setFilepath(uploadPath + FileConnect + newFileName);

        try {

            byte[] imageByte = ImageUtils.base64ImageToByte(base64Image);
            SmbFileUtils.save(imageByte,uploadPath,newFileName);
            attachment.setCreatetime(DateUtils.getNow());
            attachment.setId(UUID.randomUUID().toString());
            mpAttachmentService.add(attachment);
            return Result.success(mpAttachmentService.getView(attachment.getId()),"成功!");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed("文件上传失败");
        }
    }

    @ApiOperation(value = "获取图片", notes = "")
    @GetMapping(value="/getImage", produces = {MediaType.IMAGE_PNG_VALUE})
    public BufferedImage getImage(@ApiParam(value = "id" , required=true ) @RequestParam String id) throws IOException {
        MpAttachment attachment = mpAttachmentService.get(id);
        if(attachment !=null)
        {
            InputStream imageInputStream =  SmbFileUtils.getFile(attachment.getFilepath());
            return ImageIO.read(imageInputStream);
        }
        return null;
    }

    @ApiOperation(value = "删除", notes = "")
    @GetMapping(value="/delete")
    public Result delete(@ApiParam(value = "id" , required=true ) @RequestParam String id) {
        MpAttachment attachment = mpAttachmentService.get(id);
        try {
            SmbFileUtils.delete(attachment.getFilepath());
            int result = mpAttachmentService.delete(id);
            if(result >0){
                return Result.success(attachment,"删除成功!");
            }else {
                return Result.success(attachment,"删除失败!");
            }

        } catch (Exception e) {
            e.printStackTrace();
            return Result.failed("失败");
        }

    }

    @ModelAttribute
    public void setReqAndRes(HttpServletRequest request, HttpServletResponse response){
        this.request = request;
        this.response = response;
        this.session = request.getSession();
    }
    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }
}

jcifs文件管理帮助类

package com.brickdog.common.utils;


import jcifs.CIFSContext;
import jcifs.CIFSException;
import jcifs.context.SingletonContext;
import jcifs.smb.*;

import java.io.*;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Objects;


public class SmbFileUtils {
    static String ip = "127.0.0.1";
    static String domain = "127.0.0.1/upload";
    static String userName = "admin";
    static String password = "admin";

    static void SmbFileUtils(){

    }
    //根据账号密码登录
    private static CIFSContext withNTLMCredentials(CIFSContext ctx) {
        return ctx.withCredentials(new NtlmPasswordAuthenticator(domain,
                userName, password));
    }

    //保存文件
    public static String save(byte[] byteArr, String url,String fileName) throws IOException {
        InputStream in = new ByteArrayInputStream(byteArr);
        String status = "";
        try {
            CIFSContext context = withNTLMCredentials(SingletonContext.getInstance());
            SmbFileWriter.createDirectory("smb://" + domain  +"/" + url, context);
            boolean result = SmbFileWriter.writeSmbFile(in, "smb://" + domain  +"/" + url +"/" + fileName, context);
            status = "success";
        } catch (Exception e) {
            e.printStackTrace();
            status = "error";
        } finally {
            in.close();
            return status;
        }
    }
   
    //获取文件
    public static  InputStream getFile(String filePath) throws IOException {
        String url = "smb://" + domain + "/" + filePath;

        try {
            CIFSContext context = withNTLMCredentials(SingletonContext.getInstance());
            SmbFileReader reader = new SmbFileReader();
            SmbFile file = reader.readSmbFile(url, context);
            if (file !=null) {
                return file.getInputStream();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    //删除文件
    public static String delete(String filePath) throws IOException {
        String status = "";
        String url = "smb://" + domain + "/" + filePath;

        try {
            CIFSContext context = withNTLMCredentials(SingletonContext.getInstance());
            SmbFile file = new SmbFile(url, context);
            if (file.exists()) {
                file.delete();
                status = "success";
            }
        } catch (Exception e) {
            e.printStackTrace();
            status = "error";
        }
        return status;
    }

    static class SmbFileReader {
        public SmbFile readSmbFile(String path, CIFSContext context) throws IOException {
            try (SmbFile file = new SmbFile(path, context)) {
                if (Objects.isNull(file) || !file.exists()) {
                    throw new FileNotFoundException(path);
                }
                return file;
            }
        }
    }

    static class SmbFileWriter {
        static boolean writeSmbFile(String source, String target, CIFSContext context) throws IOException {
            if (StrUtils.isEmpty(source) || StrUtils.isEmpty(target)) {
                return false;
            }
            return writeSmbFile(Files.newInputStream(Paths.get(source)),
                    target, context);
        }

        static boolean writeSmbFile(InputStream in, String target, CIFSContext context) throws IOException {
            if (Objects.nonNull(in) && StrUtils.isNotEmpty(target)) {
                try (SmbFile file = new SmbFile(target, context)) {
                    try (SmbFile parent = new SmbFile(file.getParent(), context)) {
                        if (!parent.exists()) {
                            createDirectory(file.getParent(), context);
                        }
                        if (!file.exists()) {
                            file.createNewFile();
                        }
                    }
                    try (OutputStream os = file.getOutputStream()) {
                        byte[] bytes = new byte[1024];
                        while (in.read(bytes) != -1) {
                            os.write(bytes);
                        }
                        return true;
                    }
                }
            }
            return false;
        }

        static SmbFile createDirectory(String targetDir, CIFSContext context) throws MalformedURLException,
                CIFSException, MalformedURLException {
            try (SmbFile dir = new SmbFile(targetDir, context)) {
                if (!dir.exists()) {
                    dir.mkdir();
                }
                return dir;
            }
        }
    }
}

pom文件

这边jcifs包我们一定要使用2.0以上的,2.0以下经常会出现网盘权限认证卡住导致读取或者上传附件特别慢

<dependency>
    <groupId>eu.agno3.jcifs</groupId>
    <artifactId>jcifs-ng</artifactId>
    <version>2.1.3</version>
</dependency>

生成文件

我们对每类文件进行文件加归类,每天一个文件夹分开存放附件

?表结构

?参考文献

https://github.com/codelibs/jcifs
https://github.com/xuanyiying/jcifs-ng-smb2-demo

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:27:25  更:2022-09-13 11:27:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 4:51:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码