微信小程序实现附件(图片/视频)上传及附件(图片/视频)预览

前景:

1、框架:taro、taroUI、react;

2、图片能点击放大

3、视频能全屏播放

4、能单独删除

一、upload.js

import { Image, View, Video } from '@tarojs/components';
import React, { useEffect, useState } from 'react';
import Taro from '@tarojs/taro';
import { deleteUrl, get, post } from '../../utils/request';
import Api from '../../utils/api';
import noImg from '../../static/img/noImg.png';
import upload from '../../static/img/uploadImgVideo.png';
import './uploadImgVideo.less';

// 目前只做了单附件上传,后续再添加多附件上传
export default function UploadFile({fileId }) {

  // const [isHidden, setIsHidden] = useState(true);
  const [fileCode, setFileCode] = useState('');
  // const [sourceTypeVal] = useState(['camera']);
  // const [countVal] = useState(1);


  let [annexFiles, setAnnexFiles] = useState([]); // img
  let [annexFilesVideo, setAnnexFilesVideo] = useState([]); // img
 
  const [imgUrl, setImgUrl] = useState('');

  
  useEffect(() => {
    getFileCode();
    
  }, [fileId]);

  const getFileCode = () => {
    get(Api.file.getFileCode).then((r) => {
      if (r) {
        // setImg(upload);
        // setIsHidden(true);
        setFileCode(r);
        Taro.setStorageSync('fileCode', r);
      }
    });
  }


  // 根据fileId下载图片
  const fileView = (fileId) => {
    if (fileId) {
      post(Api.file.download,{fileId}).then((r) => {
        if (r.data) {
          // setImg(`data:image/png;base64,${r.data}`);
          setIsHidden(false);
        }
      });
    } 
  }

  const handelDel = (fileId, type, index) => {
    deleteUrl(Api.file.deleteByFileId, fileId).then((r) => {
      if (r.code === 200 && r.msg === '操作成功!') {
        if (type === 'video') {
          annexFilesVideo.splice(index, 1);
          setAnnexFilesVideo(JSON.parse(JSON.stringify(annexFilesVideo)));
        } 

        if (type === 'image') {
          annexFiles.splice(index, 1);
          setAnnexFiles(JSON.parse(JSON.stringify(annexFiles)));
        }
      }
    });
  };
 
  const addAnnex = () => {
    // let that = this;
    wx.chooseMedia({
      count: 1,
      mediaType: ['image','video'],
      sourceType: ['camera'],
      sizeType: ['original', 'compressed'],
      maxDuration: 20,
      camera: 'back',
      success(res) {
        if (res && res.tempFiles && res.tempFiles.length > 0) {
          
          let image = (res.type === "video") ? res.tempFiles[0].thumbTempFilePath : res.tempFiles[0].tempFilePath;
          const tempFilePathVideo = res.tempFiles[0].tempFilePath;
          if (res.type === "video") {
            const strs = tempFilePathVideo.split("."); //字符分割
            Taro.setStorageSync('fileCode', fileCode);
            post(Api.file.uploadVideo, {
              fileData: tempFilePathVideo,
              fileCode: fileCode,
              fileSuffixName: strs[1],
            }).then((r) => {
              if (r.code === 200 && r.msg === "上传成功!") {
                annexFilesVideo.push({type: res.type, path: res.tempFiles[0].tempFilePath, iconPath: image, id: r.data});
                setAnnexFilesVideo(JSON.parse(JSON.stringify(annexFilesVideo)));
              }
            });

          } else {
            const strs = res.tempFiles[0].tempFilePath.split("."); //字符分割
            const base64 = Taro.getFileSystemManager().readFileSync(res.tempFiles[0].tempFilePath, 'base64');

            post(Api.file.upload, {
              // clientId: 'LS-WEIXIN-WEBAPP',
              fileData: base64,
              // fileName: 'tmpImg.jpg',
              fileCode: fileCode,
              fileSuffixName: strs[1],
              }).then((r) => {
              Taro.setStorageSync('fileCode', fileCode);
              if (r.code === 200 && r.msg === "上传成功!") {
                // fileView(r.data);
                annexFiles.push({ type: res.type, path: res.tempFiles[0].tempFilePath, iconPath: image, id:  r.data});
                setAnnexFiles(JSON.parse(JSON.stringify(annexFiles)));
    
                // files1[files1.length - 1].id = r.data
              }
            });
          }

          setImgUrl(image);

        }
      },
      fail() {
        Taro.showToast({
          title: '附件添加失败!',
          icon: 'none',
          duration: 3000
        })
      }
    });
  }

  return (
    <View style={{ display: 'block' }}>
      {/* {isHidden || <View className="at-icon at-icon-close-circle upload-close" onClick={handelDel} />} */}
      <View className="imageCont">
        <View>
          
          {(annexFiles.length)
            ?
            <View>
              {/* <View className="at-row resultFont">
                <View className="at-col at-col-11">上传附件1</View>
              </View> */}
              <View className="at-row at-relative at-row--wrap resultFont">
                {annexFiles.map((item, index) => {
                  return (
                    <View className="at-col-class">
                      <View className="at-icon at-icon-close-circle upload-close" onClick={()=>handelDel(item.id, item.type, index)} />

                      <Image className="at-col-img" mode='aspectFit' src={item.iconPath}  
                              onClick={() => {
                              Taro.previewImage({
                                current: imgUrl, // 当前显示图片的http链接
                                urls: [imgUrl],
                              });
                            }} 
                      ></Image>
                    </View>
                  )
                }
                )}
              </View>
            </View>
            : ''
          }
          {(annexFilesVideo.length)
            ?
            <View className="at-row at-relative at-row--wrap resultFont">
              {annexFilesVideo.map((item, index) => {
                return (
                  <View className="at-col-class">
                    <View className="at-icon at-icon-close-circle upload-close" onClick={() => handelDel(item.id, item.type, index)} />
                    <Video
                      className="videoStyle"
                      objectFit="cover"
                      src={item.path}
                      controls={true}
                      autoplay={true}
                      initialTime={0}
                      loop={false}
                      muted={false}
                    />
                  </View>
                )
              }
              )}
            </View>
            : ''
          }
          <View className="at-col-class {{addShow?'show':'hide'}}" onClick={addAnnex}>
            <Image className="at-col-add-img" src={upload}></Image>
          </View>
        </View>
      </View>
    </View>
  );
}

export function GetFile({ fileId, fileSuffixName }) {
  let [img, setImg] = useState(noImg);

  useEffect(() => {
    if (fileId && fileSuffixName) {
      if (fileSuffixName === 'mp4') {
        post(Api.file.downloadVideo,{fileId}).then((r) => {
          if (r.data) {
            img = r.data;
            setImg(JSON.parse(JSON.stringify(img)));
            // setIsHidden(false);
          }
        });
      }
      if (fileSuffixName === 'jpg') {
        post(Api.file.download,{fileId}).then((r) => {
          if (r.data) {
            setImg(`data:image/png;base64,${r.data}`);
            // setIsHidden(false);
          }
        });
      }
      
    } 
  }, [fileId]);

  return (
    <View>
      {fileSuffixName === 'mp4'
        ?
        <Video
        id="videoViewId"
          className="upload-Image"
          objectFit="cover"
          src={img}
          controls={true}
          autoplay={true}
          initialTime={0}
          loop={false}
          muted={false}
        />
        :
        <Image
          src={img}
          className="upload-Image"
          onClick={() => {
            Taro.previewImage({
              current: img, // 当前显示图片的http链接
              urls: [img],
            });
          }} />
      }
      
    </View>
    
  );
}

二、uploadImgVideo.less


.at-row {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  width: 100%; }
.at-row__direction--row {
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -webkit-flex-direction: row;
  -ms-flex-direction: row;
  flex-direction: row; }
.at-row__direction--column {
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column; }
.at-row__direction--row-reverse {
  -webkit-box-orient: horizontal;
  -webkit-box-direction: reverse;
  -webkit-flex-direction: row-reverse;
  -ms-flex-direction: row-reverse;
  flex-direction: row-reverse; }
.at-row__direction--column-reverse {
  -webkit-box-orient: vertical;
  -webkit-box-direction: reverse;
  -webkit-flex-direction: column-reverse;
  -ms-flex-direction: column-reverse;
  flex-direction: column-reverse; }
.at-row__align--start {
  -webkit-align-items: flex-start;
  -ms-flex-align: start;
  align-items: flex-start;
  -webkit-box-align: start; }
.at-row__align--end {
  -webkit-align-items: flex-end;
  -ms-flex-align: end;
  align-items: flex-end;
  -webkit-box-align: end; }
.at-row__align--center {
  -webkit-align-items: center;
  -ms-flex-align: center;
  align-items: center;
  -webkit-box-align: center; }
.at-row__align--stretch {
  -webkit-align-items: stretch;
  -ms-flex-align: stretch;
  align-items: stretch;
  -webkit-box-align: stretch; }
.at-row__align--baseline {
  -webkit-align-items: baseline;
  -ms-flex-align: baseline;
  align-items: baseline;
  -webkit-box-align: baseline; }
.at-row__justify--start {
  -webkit-justify-content: flex-start;
  -ms-flex-pack: start;
  justify-content: flex-start;
  -webkit-box-pack: start; }
.at-row__justify--end {
  -webkit-justify-content: flex-end;
  -ms-flex-pack: end;
  justify-content: flex-end;
  -webkit-box-pack: end; }
.at-row__justify--center {
  -webkit-justify-content: center;
  -ms-flex-pack: center;
  justify-content: center;
  -webkit-box-pack: center; }
.at-row__justify--between {
  -webkit-justify-content: space-between;
  -ms-flex-pack: justify;
  justify-content: space-between;
  -webkit-box-pack: justify; }
.at-row__justify--around {
  -webkit-justify-content: space-around;
  -ms-flex-pack: distribute;
  justify-content: space-around;
  -webkit-box-pack: space-around; }
.at-row__align-content--start {
  -webkit-align-content: flex-start;
  -ms-flex-line-pack: start;
  align-content: flex-start; }
.at-row__align-content--end {
  -webkit-align-content: flex-end;
  -ms-flex-line-pack: end;
  align-content: flex-end; }
.at-row__align-content--center {
  -webkit-align-content: center;
  -ms-flex-line-pack: center;
  align-content: center; }
.at-row__align-content--between {
  -webkit-align-content: space-between;
  -ms-flex-line-pack: justify;
  align-content: space-between; }
.at-row__align-content--around {
  -webkit-align-content: space-around;
  -ms-flex-line-pack: distribute;
  align-content: space-around; }
.at-row__align-content--stretch {
  -webkit-align-content: stretch;
  -ms-flex-line-pack: stretch;
  align-content: stretch; }
.at-row--no-wrap {
  -webkit-flex-wrap: nowrap;
  -ms-flex-wrap: nowrap;
  flex-wrap: nowrap; }
.at-row--wrap {
  -webkit-flex-wrap: wrap;
  -ms-flex-wrap: wrap;
  flex-wrap: wrap; }
.at-row--wrap-reverse {
  -webkit-flex-wrap: wrap-reverse;
  -ms-flex-wrap: wrap-reverse;
  flex-wrap: wrap-reverse; }
 
.at-col {
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
  -webkit-box-flex: 1;
  width: 100%;
  display: block;
  white-space: nowrap;
  -webkit-box-sizing: border-box;
  box-sizing: border-box; }
.at-col-1 {
  -webkit-flex: 0 0 8.33333%;
  -ms-flex: 0 0 8.33333%;
  flex: 0 0 8.33333%;
  -webkit-box-flex: 0;
  max-width: 8.33333%; }
.at-col__offset-1 {
  margin-left: 8.33333%; }
.at-col-2 {
  -webkit-flex: 0 0 16.66667%;
  -ms-flex: 0 0 16.66667%;
  flex: 0 0 16.66667%;
  -webkit-box-flex: 0;
  max-width: 16.66667%; }
.at-col__offset-2 {
  margin-left: 16.66667%; }
.at-col-3 {
  -webkit-flex: 0 0 25%;
  -ms-flex: 0 0 25%;
  flex: 0 0 25%;
  -webkit-box-flex: 0;
  max-width: 25%; }
.at-col__offset-3 {
  margin-left: 25%; }
.at-col-4 {
  -webkit-flex: 0 0 33.33333%;
  -ms-flex: 0 0 33.33333%;
  flex: 0 0 33.33333%;
  -webkit-box-flex: 0;
  max-width: 33.33333%; }
.at-col__offset-4 {
  margin-left: 33.33333%; }
.at-col-5 {
  -webkit-flex: 0 0 41.66667%;
  -ms-flex: 0 0 41.66667%;
  flex: 0 0 41.66667%;
  -webkit-box-flex: 0;
  max-width: 41.66667%; }
.at-col__offset-5 {
  margin-left: 41.66667%; }
.at-col-6 {
  -webkit-flex: 0 0 50%;
  -ms-flex: 0 0 50%;
  flex: 0 0 50%;
  -webkit-box-flex: 0;
  max-width: 50%; }
.at-col__offset-6 {
  margin-left: 50%; }
.at-col-7 {
  -webkit-flex: 0 0 58.33333%;
  -ms-flex: 0 0 58.33333%;
  flex: 0 0 58.33333%;
  -webkit-box-flex: 0;
  max-width: 58.33333%; }
.at-col__offset-7 {
  margin-left: 58.33333%; }
.at-col-8 {
  -webkit-flex: 0 0 66.66667%;
  -ms-flex: 0 0 66.66667%;
  flex: 0 0 66.66667%;
  -webkit-box-flex: 0;
  max-width: 66.66667%; }
.at-col__offset-8 {
  margin-left: 66.66667%; }
.at-col-9 {
  -webkit-flex: 0 0 75%;
  -ms-flex: 0 0 75%;
  flex: 0 0 75%;
  -webkit-box-flex: 0;
  max-width: 75%; }
.at-col__offset-9 {
  margin-left: 75%; }
.at-col-10 {
  -webkit-flex: 0 0 83.33333%;
  -ms-flex: 0 0 83.33333%;
  flex: 0 0 83.33333%;
  -webkit-box-flex: 0;
  max-width: 83.33333%; }
.at-col__offset-10 {
  margin-left: 83.33333%; }
.at-col-11 {
  -webkit-flex: 0 0 91.66667%;
  -ms-flex: 0 0 91.66667%;
  flex: 0 0 91.66667%;
  -webkit-box-flex: 0;
  max-width: 91.66667%; }
.at-col__offset-11 {
  margin-left: 91.66667%; }
.at-col-12 {
  -webkit-flex: 0 0 100%;
  -ms-flex: 0 0 100%;
  flex: 0 0 100%;
  -webkit-box-flex: 0;
  max-width: 100%; }
.at-col__offset-12 {
  margin-left: 100%; }
.at-col__align--top {
  -webkit-align-self: flex-start;
  -ms-flex-item-align: start;
  align-self: flex-start; }
.at-col__align--bottom {
  -webkit-align-self: flex-end;
  -ms-flex-item-align: end;
  align-self: flex-end; }
.at-col__align--center {
  -webkit-align-self: center;
  -ms-flex-item-align: center;
  align-self: center; }
.at-col--auto {
  max-width: initial;
  word-break: keep-all; }
.at-col--wrap {
  white-space: normal;
  word-wrap: break-word; }
 
.annex {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  visibility: hidden;
  -webkit-transition: visibility 200ms ease-in;
  -o-transition: visibility 200ms ease-in;
  transition: visibility 200ms ease-in;
  z-index: 1000;
}
.annex--active {
  visibility: visible;
}
.annex--active .annex__overlay,
.annex--active .annex__container {
  opacity: 1;
}
.annex__overlay {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  position: absolute;
  background-color: rgba(0, 0, 0, 0.3);
}
.annex__container {
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  width: 600rpx;
  max-height: calc(100vh - 300rpx);
  overflow: hidden;
  border-radius: 12rpx;
}
.annex__overlay, .annex__container {
  opacity: 0;
  -webkit-transition: opacity 200ms ease-in;
  -o-transition: opacity 200ms ease-in;
  transition: opacity 200ms ease-in;
}
 
 
.at-relative {
  position: relative;
}
.at-col-class {
  width: 222rpx !important;
  height: 222rpx !important;
  margin: 5rpx;
  text-align: center;
  border: 2rpx #d6e4ef solid;
  position: relative;
  display: block;
  white-space: nowrap;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}
.at-col-img {
  width: 218rpx !important;
  height: 218rpx !important;
}
.at-col-close {
  width: 36rpx;
  height: 36rpx;
  position: absolute;
  top: 2rpx;
  right: 2rpx;
  border-radius: 100%;
  background-color: #ffffff;
  z-index: 99;
}
.at-col-add-img {
  width:222rpx;
  height:222rpx;
  // margin: 69rpx 85rpx auto 85rpx;
}
.at-col-add-text {
  margin-top: 30rpx;
  color: #999999;
}
.resultFont {
  font-size:32rpx;
  margin-top:30rpx;
}
.count_color {
  color: #CCCCCC;
}
// .hide {
//   display: none !important;
// }
.show {
  display: block;
}
.w100 {
  width: 100%;
}
.videoStyle{
  height: 220rpx;
  width: 220rpx;
}
.upload-close {
  font-size: 38rpx;
  z-index: 999;
  position: absolute;
  top: 20rpx;
  right: 40rpx;
  color: #ccc;
  margin: -20rpx -43rpx;
}

三、上传时直接引用

import UploadFile from '../../components/upload/upload';


<View className="uploadView">
   <View>上传附件:</View>
   <View>
      <UploadFile fileCode={fileCode} />
   </View>
</View>

四、上传效果

五、直接查看视频/图片

flieIds:后端传的视频\图片的ids

import { GetFile } from '../../components/upload/upload';


{
  (flieIds.length) ?
   <View className="uploadView">
      <View>附件:</View>
      <View>
        {flieIds.map((item, index) => {
          return (
            <GetFile fileId = {item.fileId} fileSuffixName = {item.fileSuffixName}/>
          )
         })}
      </View>
   </View> : ''
 }

六、图片(可直接点击下载)

1、import upload from '../../static/img/uploadImgVideo.png

2、import noImg from '../../static/img/noImg.png';

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值