Vue+SpringBoot文件上传下载及PDF和图片在线展示

1、vue前端部分

前端部分采用element组件
官网上传下载的地址地址
主要的element代码如下,下面我一一的讲解一下

 <el-form-item>
        <el-upload
          drag
          :action="url"
          ref="upload"
          :before-upload="beforeUploadHandle"
          :on-success="successHandle"
          :on-change="handleChange"
          multiple
          :file-list="fileList"
          :limit="1"
          :on-exceed="handleExceed"
          style="text-align: center"
          :auto-upload="false"
        >
          <el-button size="small" type="primary">点击上传</el-button>
        </el-upload>
      </el-form-item>

drag:支持拖拽的效果
:action=“url” :绑定的URL,上传的url,默认的的post方式上传,这个我也找了半天才明白过来
ref=“upload” :可以理解成上传组件的ID,绑定的是upload
:before-upload=“beforeUploadHandle”:在上传之前绑定的方法,一般里面做一下判断,比如判断文件属性
:on-success=“successHandle” :上传成功时候调用的方法
:on-change="handleChange"上传文件组件,状态改变时候调用的方法
multiple :是否支持多文件上传
:file-list :上传的组件列表,在下面显示
:limit=“1”:限制上传的数量
:on-exceed=“handleExceed” 文件超出个数限制时的钩子,当文件超出limit限制的值,会调用这个函数
:auto-upload=“false” 这个是很关键的,element上传组件,这个是默认true。也就是说,点击上传后,直接就上传了,这个设置为false与则不会自动上传
this. r e f s . u p l o a d . s u b m i t ( ) ; 文件提交 t h i s . refs.upload.submit(); 文件提交 this. refs.upload.submit();文件提交this.refs.upload.clearFiles 清除上传记录在这里插入图片描述
在这里插入图片描述

2、Vue上传前端方法部分

data里面

这个里面设置 document 是拿取到文件的名称,并赋值,uid是elementUI根据时间随机生成的UId,我也拿取来作为参数存储下来,给后端生成文件夹使用,并存储到数据库

data() {
    return {
       url: "",
      num: 0,
      successNum: 0,
      fileList: [],
      document: "",
      uid: "",
    }}

方法部分
initUrl这个可以作为初始化,create(){}里面初始化上传地址使用,我这里url是带token值传参的
handleExceed()超出绑定的 limit 限制时候调用
beforeUploadHandle()在上传前面,判断文件上传的类型
handleChange()当添加了文件的时候调用,我这里在文件路径后面加入了uid
successHandle()上传成功时候调用

  initUrl(id) {
      this.url = this.$http.adornUrl(
        `/sys/oss/upload3?token=${this.$cookie.get("token")}` +
          `&uid=` +
          this.uid
      );
    },

    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 1 个文件,本次上传数量超过限制`);
      this.fileList = [];
    },
    // 上传之前
    beforeUploadHandle(file) {
      // if (
      //   file.type !== "image/jpg" &&
      //   file.type !== "image/jpeg" &&
      //   file.type !== "image/png" &&
      //   file.type !== "image/gif"
      // ) {
      //   this.$message.error("只支持jpg、png、gif格式的图片!");
      //   return false;
      // }
      this.num++;
    },
    upclick() {
      this.visible = true;
    },
    // 上传成功
    successHandle(response, file, fileList) {
      this.fileList = fileList;
      console.log(response);
      console.log(file);
      console.log(fileList);
      this.successNum++;
      if (response && response.code === 0) {
        if (this.num === this.successNum) {
          this.$confirm("操作成功, 是否继续操作?", "提示", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
          }).catch(() => {
            this.visible = false;
          });
        }
      } else {
        this.$message.error(response.msg);
      }
    },
    // 弹窗关闭时
    closeHandle() {
      this.fileList = [];
      this.$emit("refreshDataList");
    },
    handleChange(file, fileList) {
      this.document = file.name;
      this.uid = file.uid;
      console.log(file.name);
      console.log(file.uid);
      this.url =
        this.$http.adornUrl(`/sys/oss/upload3?`) +
        `token=${this.$cookie.get("token")}` +
        `&uid=` +
        file.uid;
      console.log(this.url);
    },

文件提交的方法,因为配置的 :auto-upload=“false” ,所以需要手动提交传入文件,传输完文件之后,this.$refs.upload.clearFiles();将文件清空处理

 if (this.fileList != null) {
            console.log(this.url);
            this.$refs.upload.submit();
            this.$nextTick(() => {
              this.$refs.upload.clearFiles();
            });
  }

3、Springboot后端上传文件接口

解释几点
1、File.separator:系统的分隔符 /
2、HttpServletRequest req 可以拿到URL?uid=***,这种url的参数
String sid = req.getParameter(“uid”);我把这个随机的uid作为参数拿到并作为文件夹的,这样文件就出现不会被覆盖的问题
3、当然这个MultipartFile[]是支持多文件上传的
4、Streams.copy(multipartFiles[i].getInputStream(), new FileOutputStream(storagePath),拿到输入流和路径,开始上传

@Autowired
	UnitService unitService;

	private static final Logger logger = LoggerFactory.getLogger(UnitController.class);
	//在文件操作中,不用/或者\最好,推荐使用File.separator
	private final static String fileDir = "files";
	private final static String rootPath = System.getProperty("user.home") + File.separator + fileDir + File.separator;

	@PostMapping("/upload3")
	@RequiresPermissions("sys:oss:all")
	public R upload2(@RequestParam("file") MultipartFile[] multipartFiles, HttpServletRequest req) {

		String sid = req.getParameter("uid");
		String uid = sid;
		String path=rootPath;
		if(uid!=null){
			path=path+uid+File.separator;
			System.out.println(uid);
		}
		System.out.println(uid);

		File fileDir = new File(path);
		if (!fileDir.exists() && !fileDir.isDirectory()) {
			fileDir.mkdirs();
		}
		try {
			if (multipartFiles != null && multipartFiles.length > 0) {

				for (int i = 0; i < multipartFiles.length; i++) {
					System.out.println(multipartFiles[i].getResource());
					try {
						//以原来的名称命名,覆盖掉旧的
						String storagePath = path + multipartFiles[i].getOriginalFilename();
						logger.info("上传的文件:" + multipartFiles[i].getName() + "," + multipartFiles[i].getContentType() + "," + multipartFiles[i].getOriginalFilename()
								+ ",保存的路径为:" + storagePath);
						Streams.copy(multipartFiles[i].getInputStream(), new FileOutputStream(storagePath), true);
						//或者下面的
						// Path path = Paths.get(storagePath);
						//Files.write(path,multipartFiles[i].getBytes());
					} catch (IOException e) {

					}
				}
			}

		} catch (Exception e) {
			return R.error(e.getMessage());
		}
		return R.ok("上传成功!");
	}

4、Vue前端下载文件

下载的样式

 <el-button
            type="text"
            icon="el-icon-download"
            class="blue"
            @click="handleDownload(scope.$index, scope.row)"
            >下载</el-button
          >
        </template>

下载的方法
主要是配置一个elemIF.src =url这样,我同样是带token值的,下载默认get方式下载

    async handleDownload(index, row) {
      console.log(row)
      console.log(row.document)
      this.loadingOverLay = this.$loading({
        lock: true,
        text: "文件生成中",
        spinner: "el-icon-loading",
        background: "rgba(0,0,0,0.7)",
      });
      var elemIF = document.createElement("iframe");
      elemIF.src =
        this.$http.adornUrl(
        `/sys/oss/download?`
      ) +`token=${this.$cookie.get("token")}`+`&id=`+row.id;
        
      elemIF.style.display = "none";
      document.body.appendChild(elemIF);
      this.loadingOverLay.close();

    },

5、SpringBoot下载接口(可以通用)

download的方法是下载方法,
setFileDownloadHeader方法是处理乱码问题的方法
我是通过ID查询到数据查询到文件的名称和路径,返回下载的

@RequiresPermissions("sys:oss:all")
	@GetMapping(value = "/download")
	public void download(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println(req);
		String sid = req.getParameter("id");
		int id = Integer.parseInt(sid);
		UnitEntity documentById = unitService.findDocumentById(id);
		String location=documentById.getFileaddress();
		String fileName=documentById.getDocument();
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		OutputStream fos = null;
		try {
			bis = new BufferedInputStream(new FileInputStream(location));
			fos = resp.getOutputStream();
			bos = new BufferedOutputStream(fos);
			setFileDownloadHeader(req, resp, fileName);
			int byteRead = 0;
			byte[] buffer = new byte[8192];
			while ((byteRead = bis.read(buffer, 0, 8192)) != -1) {
				bos.write(buffer, 0, byteRead);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				bos.flush();
				bis.close();
				fos.close();
				bos.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void setFileDownloadHeader(HttpServletRequest request,
											 HttpServletResponse response, String fileName) {
		try {
			String encodedFileName = null;
			String agent = request.getHeader("USER-AGENT");
			if (null != agent && -1 != agent.indexOf("MSIE")) {
				encodedFileName = URLEncoder.encode(fileName, "UTF-8");
			} else if (null != agent && -1 != agent.indexOf("Mozilla")) {
				encodedFileName = new String(fileName.getBytes("UTF-8"),
						"iso-8859-1");
			} else {
				encodedFileName = URLEncoder.encode(fileName, "UTF-8");
			}

			response.setHeader("Content-Disposition", "attachment; filename=\""
					+ encodedFileName + "\"");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

6、在线展示PDF和图片后台

前端只需要调用一个网址就能查看图片和PDF

代码逻辑如下,
(1)、前端查看接口XXXX:8080/showPicture?id=***
(2)后端通过req.getParameter(“id”);拿到Id在数据库中查到PDF的绝对地址,
(3)、通过showPdf渲染就能在线查看pdf了

   @RequiresPermissions("generator:area:update")
    @GetMapping("/showPicture")
    public R showPicture(HttpServletResponse response, HttpServletRequest req){
        try {
            String sid = req.getParameter("id");
            int id = Integer.parseInt(sid);
            AreaFileEntity byId = areaFileService.getById(id);
            String location = byId.getFileaddress();
            showPdf(response,location);
            return R.ok();
        }catch (Exception e) {
            e.printStackTrace();
            return R.error("传输失败");
        }
    }

    public static void showPdf(HttpServletResponse response, String fileName) throws IOException {
//        response.setContentType("application/pdf");
        response.addHeader("Access-Control-Allow-Origin", "*");
        FileInputStream in = new FileInputStream(new File(fileName));
        OutputStream out = response.getOutputStream();
        byte[] b = new byte[1024];
        while ((in.read(b))!=-1) {
            out.write(b);
        }
        out.flush();
        in.close();
        out.close();
    }

7、文件上传,采用FormData封装数据接口

前端:(点击上传后,直接调用接口,上传图片)

<el-upload
          class="avatar-uploader"
          accept="image/*"
          action=""
          :show-file-list="false"
          :http-request="uploadMainImg"
        >
          <img
            v-if="formData.imageUrl"
            :src="formData.imageUrl"
            class="avatar"
          />
          <i v-else class="el-icon-plus avatar-uploader-icon"></i>
        </el-upload>

前端样式

.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}

前端上传方法

  //上传图片
    uploadMainImg(file) {
      const data = new FormData();
      data.append("file", file.file);
      data.append("uid", file.file.uid);
      console.log(file.file)
      commonApi
        .uploadImg(data)
        .then((response) => {
          //  以防图片多次上传,上传成功后,把原来的图片删除
          this.deleteImg();
          this.formData.imageUrl = response.data;
        })
        .catch((error) => {
          this.$message({
            type: "error",
            message: "上传失败",
          });
        });
    },

前端接口

   // 上传图片
    uploadImg(data = {}) {
        return request({
            url: `/article/file/upload`,
            method: 'post',
            data // data: data 简写
        })
    },

## 后端
后端接口

  @PostMapping("/upload")
    public Result upLoad(@RequestParam(value="file") MultipartFile file,@RequestParam(value="uid")String uid) {
       
        Result result1 = AliyunUtil.upLoadLocal(file);
        System.out.println("uid等于"+uid);
        return result1;

    }

后端上传工具

    private final static String fileDir = "workFiles";
    private final static String rootPath = System.getProperty("user.home") + File.separator + fileDir + File.separator;

    public static Result upLoadLocal(MultipartFile multipartFiles){

        File fileDir = new File(rootPath);


        if (!fileDir.exists() && !fileDir.isDirectory()) {
            fileDir.mkdirs();
        }

        try {
            if (multipartFiles != null ) {
                    try {
                        //以原来的名称命名,覆盖掉旧的
                        String storagePath = rootPath + multipartFiles.getOriginalFilename();
                        System.out.println("上传的文件:" + multipartFiles.getName() + "," + multipartFiles.getContentType() + "," + multipartFiles.getOriginalFilename()
                                + ",保存的路径为:" + storagePath);
                        Streams.copy(multipartFiles.getInputStream(), new FileOutputStream(storagePath), true);
                        return Result.ok(storagePath);
                    } catch (IOException e) {
                        return Result.ok("失败!");
                    }

            }

        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
     return Result.ok("失败!");
    }

minIo文件分片上传并显示文件上传进度

1、

  • 2
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
你可以使用Vue.js和Element UI来实现前端界面,使用Spring Boot来处理后端逻辑来实现文件模板的上传下载功能。 首先,你可以创建一个Vue组件来处理文件上传下载的界面。可以使用Element UI中的Upload组件来实现文件上传功能,使用Button组件来实现文件下载功能。在上传组件中,你可以设置上传文件类型和大小限制,并在上传成功后获取到文件的URL或者其他信息。 接下来,在后端使用Spring Boot来处理上传下载的逻辑。你可以创建一个Controller来处理文件上传下载的请求。在文件上传的方法中,你可以使用MultipartFile来接收上传文件,并将其保存到服务器上的某个目录中。在文件下载的方法中,你可以根据传入的文件名或者其他标识,从服务器上读取相应的文件,并将其以流的形式返回给前端。 以下是一个简单的示例代码: 前端Vue.js + Element UI): ```vue <template> <div> <el-upload class="upload-demo" action="/api/upload" :on-success="handleSuccess" :before-upload="beforeUpload" > <el-button type="primary">点击上传</el-button> </el-upload> <el-button type="primary" @click="downloadTemplate">下载模板</el-button> </div> </template> <script> export default { methods: { handleSuccess(response) { // 处理上传成功后的逻辑 console.log(response); }, beforeUpload(file) { // 设置上传文件的类型和大小限制 const fileType = file.type; const fileSize = file.size / 1024 / 1024; // MB const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']; // 允许的文件类型 const maxFileSize = 10; // 允许的最大文件大小,单位:MB if (!allowedTypes.includes(fileType)) { this.$message.error('只能上传pdf、doc或docx格式的文件'); return false; } if (fileSize > maxFileSize) { this.$message.error(`文件大小超过了${maxFileSize}MB`); return false; } return true; }, downloadTemplate() { // 处理下载模板的逻辑 window.location.href = '/api/download'; }, }, }; </script> ``` 后端(Spring Boot): ```java @RestController @RequestMapping("/api") public class FileController { @PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file) { // 处理文件上传逻辑 // 可以将上传文件保存到服务器上的某个目录中 return "上传成功"; } @GetMapping("/download") public void downloadTemplate(HttpServletResponse response) { // 处理文件下载逻辑 // 根据文件名或者其他标识,从服务器上读取相应的文件,并将其以流的形式返回给前端 String fileName = "template.docx"; // 下载文件名 String filePath = "/path/to/template.docx"; // 文件在服务器上的路径 try { File file = new File(filePath); InputStream inputStream = new FileInputStream(file); response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8")); IOUtils.copy(inputStream, response.getOutputStream()); response.flushBuffer(); } catch (Exception e) { e.printStackTrace(); } } } ``` 这是一个简单的示例,你可以根据自己的需求进行进一步的调整和优化。希望对你有帮助!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值