我就废话不多说了,大家还是直接看代码吧~
- <template>
- <uploader :options="options" :file-status-text="statusText" class="uploader-example" ref="uploader" @file-success="fileSuccess"></uploader>
- </template>
- <script>
- export default {
- data () {
- return {
- options: {
- target: '//localhost:3000/upload', // '//jsonplaceholder.typicode.com/posts/',
- testChunks: false
- },
- attrs: {
- accept: 'image/*'
- },
- statusText: {
- success: '成功了',
- error: '出错了',
- uploading: '上传中',
- paused: '暂停中',
- waiting: '等待中'
- }
- }
- },
- methods: {
- //上传成功的事件
- fileSuccess (rootFile, file, message, chunk) {
- console.log('complete', rootFile, file, message, chunk)
- }
- },
- mounted () {
- // 获取uploader对象
- this.$nextTick(() => {
- window.uploader = this.$refs.uploader.uploader
- })
- }
- }
- </script>
补充知识:利用SpringBoot和vue-simple-uploader进行文件的分片上传
效果【上传Zip文件为例,可以自行扩展】
引入vue-simple-uploader
1.安装上传插件
npm install vue-simple-uploader --save
2.main.js全局引入上传插件
import uploader from 'vue-simple-uploader'
Vue.use(uploader)
3.安装md5校验插件(保证上传文件的完整性和一致性)
npm install spark-md5 --save
页面
- <template>
- <div>
- <uploader :key="uploader_key" :options="options" class="uploader-example"
- :autoStart="false"
- @file-success="onFileSuccess"
- @file-added="filesAdded">
- <uploader-unsupport></uploader-unsupport>
- <uploader-drop>
- <uploader-btn :single="true" :attrs="attrs">选择Zip文件</uploader-btn>
- </uploader-drop>
- <uploader-list></uploader-list>
- </uploader>
- </div>
- </template>
- <script>
- import SparkMD5 from 'spark-md5';
- export default {
- data() {
- return {
- uploader_key: new Date().getTime(),
- options: {
- target: '/chunk/chunkUpload',
- testChunks: false,
- },
- attrs: {
- accept: '.zip'
- }
- }
- },
- methods: {
- onFileSuccess: function (rootFile, file, response, chunk) {
- console.log(JSON.parse(response).model);
- },
- computeMD5(file) {
- const loading = this.$loading({
- lock: true,
- text: '正在计算MD5',
- spinner: 'el-icon-loading',
- background: 'rgba(0, 0, 0, 0.7)'
- });
- let fileReader = new FileReader();
- let time = new Date().getTime();
- let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
- let currentChunk = 0;
- const chunkSize = 10 * 1024 * 1000;
- let chunks = Math.ceil(file.size / chunkSize);
- let spark = new SparkMD5.ArrayBuffer();
- file.pause();
- loadNext();
- fileReader.onload = (e => {
- spark.append(e.target.result);
- if (currentChunk < chunks) {
- currentChunk++;
- loadNext();
- this.$nextTick(() => {
- console.log('校验MD5 ' + ((currentChunk / chunks) * 100).toFixed(0) + '%')
- })
- } else {
- let md5 = spark.end();
- loading.close();
- this.computeMD5Success(md5, file);
- console.log(`MD5计算完毕:${file.name} \nMD5:${md5} \n分片:${chunks} 大小:${file.size} 用时:${new Date().getTime() - time} ms`);
- }
- });
- fileReader.onerror = function () {
- this.error(`文件${file.name}读取出错,请检查该文件`);
- loading.close();
- file.cancel();
- };
- function loadNext() {
- let start = currentChunk * chunkSize;
- let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
- fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
- }
- },
- computeMD5Success(md5, file) {
- file.uniqueIdentifier = md5;//把md5值作为文件的识别码
- file.resume();//开始上传
- },
- filesAdded(file, event) {
- //大小判断
- const isLt100M = file.size / 1024 / 1024 < 10;
- if (!isLt100M) {
- this.$message.error(this.$t("error.error_upload_file_max"));
- } else {
- this.computeMD5(file)
- }
- }
- }
- }
- </script>
- <style>
- .uploader-example {
- width: 90%;
- padding: 15px;
- margin: 40px auto 0;
- font-size: 12px;
- box-shadow: 0 0 10px rgba(0, 0, 0, .4);
- }
- .uploader-example .uploader-btn {
- margin-right: 4px;
- }
- .uploader-example .uploader-list {
- max-height: 440px;
- overflow: auto;
- overflow-x: hidden;
- overflow-y: auto;
- }
- </style>
后台
引入工具
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.6</version>
- </dependency>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.6</version>
- </dependency>
控制类
- import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.File;
- @RestController
- @RequestMapping("/chunk")
- public class ChunkController {
- @RequestMapping("/chunkUpload")
- public StdOut chunkUpload(MultipartFileParam param, HttpServletRequest request, HttpServletResponse response) {
- StdOut out = new StdOut();
- File file = new File("C:\\chunk_test");//存储路径
- ChunkService chunkService = new ChunkService();
- String path = file.getAbsolutePath();
- response.setContentType("text/html;charset=UTF-8");
- try {
- //判断前端Form表单格式是否支持文件上传
- boolean isMultipart = ServletFileUpload.isMultipartContent(request);
- if (!isMultipart) {
- out.setCode(StdOut.PARAMETER_NULL);
- out.setMessage("表单格式错误");
- return out;
- } else {
- param.setTaskId(param.getIdentifier());
- out.setModel(chunkService.chunkUploadByMappedByteBuffer(param, path));
- return out;
- }
- } catch (NotSameFileExpection e) {
- out.setCode(StdOut.FAIL);
- out.setMessage("MD5校验失败");
- return out;
- } catch (Exception e) {
- out.setCode(StdOut.FAIL);
- out.setMessage("上传失败");
- return out;
- }
- }
- }
StdOut类(只是封装的返回类)
- public class StdOut {
- public static final int SUCCESS = 200;
- public static final int FAIL = 400;
- public static final int PARAMETER_NULL = 500;
- public static final int NO_LOGIN = 600;
- private int code = 200;
- private Object model = null;
- private String message = null;
- public StdOut() {
- this.setCode(200);
- this.setModel((Object)null);
- }
- public StdOut(int code) {
- this.setCode(code);
- this.setModel((Object)null);
- }
- public StdOut(List<Map<String, Object>> model) {
- this.setCode(200);
- this.setModel(model);
- }
- public StdOut(int code, List<Map<String, Object>> model) {
- this.setCode(code);
- this.setModel(model);
- }
- public int getCode() {
- return this.code;
- }
- public void setCode(int code) {
- this.code = code;
- }
- public String toString() {
- return JSON.toJSONString(this);
- }
- public Object getModel() {
- return this.model;
- }
- public void setModel(Object model) {
- this.model = model;
- }
- public String getMessage() {
- return this.message;
- }
- public void setMessage(String message) {
- this.message = message;
- }
- }
MultipartFileParam类(文件信息类)
- import org.springframework.web.multipart.MultipartFile;
- public class MultipartFileParam {
- private String taskId;
- private int chunkNumber;
- private long chunkSize;
- private int totalChunks;
- private String identifier;
- private MultipartFile file;
- public String getTaskId() {
- return taskId;
- }
- public void setTaskId(String taskId) {
- this.taskId = taskId;
- }
- public int getChunkNumber() {
- return chunkNumber;
- }
- public void setChunkNumber(int chunkNumber) {
- this.chunkNumber = chunkNumber;
- }
- public long getChunkSize() {
- return chunkSize;
- }
- public void setChunkSize(long chunkSize) {
- this.chunkSize = chunkSize;
- }
- public int getTotalChunks() {
- return totalChunks;
- }
- public void setTotalChunks(int totalChunks) {
- this.totalChunks = totalChunks;
- }
- public String getIdentifier() {
- return identifier;
- }
- public void setIdentifier(String identifier) {
- this.identifier = identifier;
- }
- public MultipartFile getFile() {
- return file;
- }
- public void setFile(MultipartFile file) {
- this.file = file;
- }
- }
ChunkService类
- import org.apache.commons.codec.digest.DigestUtils;
- import org.apache.commons.io.FileUtils;
- import org.apache.commons.lang.StringUtils;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.RandomAccessFile;
- import java.nio.ByteBuffer;
- import java.nio.channels.FileChannel;
- import java.util.UUID;
- public class ChunkService {
- public String chunkUploadByMappedByteBuffer(MultipartFileParam param, String filePath) throws IOException, NotSameFileExpection {
- if (param.getTaskId() == null || "".equals(param.getTaskId())) {
- param.setTaskId(UUID.randomUUID().toString());
- }
- String fileName = param.getFile().getOriginalFilename();
- String tempFileName = param.getTaskId() + fileName.substring(fileName.lastIndexOf(".")) + "_tmp";
- File fileDir = new File(filePath);
- if (!fileDir.exists()) {
- fileDir.mkdirs();
- }
- File tempFile = new File(filePath, tempFileName);
- //第一步 打开将要写入的文件
- RandomAccessFile raf = new RandomAccessFile(tempFile, "rw");
- //第二步 打开通道
- FileChannel fileChannel = raf.getChannel();
- //第三步 计算偏移量
- long position = (param.getChunkNumber() - 1) * param.getChunkSize();
- //第四步 获取分片数据
- byte[] fileData = param.getFile().getBytes();
- //第五步 写入数据
- fileChannel.position(position);
- fileChannel.write(ByteBuffer.wrap(fileData));
- fileChannel.force(true);
- fileChannel.close();
- raf.close();
- //判断是否完成文件的传输并进行校验与重命名
- boolean isComplete = checkUploadStatus(param, fileName, filePath);
- if (isComplete) {
- FileInputStream fileInputStream = new FileInputStream(tempFile.getPath());
- String md5 = DigestUtils.md5Hex(fileInputStream);
- fileInputStream.close();
- if (StringUtils.isNotBlank(md5) && !md5.equals(param.getIdentifier())) {
- throw new NotSameFileExpection();
- }
- renameFile(tempFile, fileName);
- return fileName;
- }
- return null;
- }
- public void renameFile(File toBeRenamed, String toFileNewName) {
- if (!toBeRenamed.exists() || toBeRenamed.isDirectory()) {
- System.err.println("文件不存在");
- return;
- }
- String p = toBeRenamed.getParent();
- File newFile = new File(p + File.separatorChar + toFileNewName);
- toBeRenamed.renameTo(newFile);
- }
- public boolean checkUploadStatus(MultipartFileParam param, String fileName, String filePath) throws IOException {
- File confFile = new File(filePath, fileName + ".conf");
- RandomAccessFile confAccessFile = new RandomAccessFile(confFile, "rw");
- //设置文件长度
- confAccessFile.setLength(param.getTotalChunks());
- //设置起始偏移量
- confAccessFile.seek(param.getChunkNumber() - 1);
- //将指定的一个字节写入文件中 127,
- confAccessFile.write(Byte.MAX_VALUE);
- byte[] completeStatusList = FileUtils.readFileToByteArray(confFile);
- confAccessFile.close();//不关闭会造成无法占用
- //创建conf文件文件长度为总分片数,每上传一个分块即向conf文件中写入一个127,那么没上传的位置就是默认的0,已上传的就是127
- for (int i = 0; i < completeStatusList.length; i++) {
- if (completeStatusList[i] != Byte.MAX_VALUE) {
- return false;
- }
- }
- confFile.delete();
- return true;
- }
- }
6.NotSameFileExpection类
- public class NotSameFileExpection extends Exception {
- public NotSameFileExpection() {
- super("File MD5 Different");
- }
- }
遇到问题
根据自己的实际情况进行取舍,灵活处理。
以上这篇vue-simple-uploader上传成功之后的response获取代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。
原文链接:https://blog.csdn.net/BennyShi1998/article/details/79326551