017_Upload上传

1. Upload上传

1.1. 通过点击或者拖拽上传文件。

1.2. Upload上传属性

参数

说明

类型

可选值

默认值

action

必选参数, 上传的地址

string

headers

设置上传的请求头部

object

multiple

是否支持多选文件

boolean

data

上传时附带的额外参数

object

name

上传的文件字段名

string

file

with-credentials

支持发送cookie凭证信息

boolean

false

show-file-list

是否显示已上传文件列表

boolean

true

drag

是否启用拖拽上传

boolean

false

accept

接受上传的文件类型(thumbnail-mode 模式下此参数无效)

string

on-preview

点击文件列表中已上传的文件时的钩子

function(file)

on-remove

文件列表移除文件时的钩子

function(file, fileList)

on-success

文件上传成功时的钩子

function(response, file, fileList)

on-error

文件上传失败时的钩子

function(err, file, fileList)

on-progress

文件上传时的钩子

function(event, file, fileList)

on-change

文件状态改变时的钩子, 添加文件、上传成功和上传失败时都会被调用

function(file, fileList)

before-upload

上传文件之前的钩子, 参数为上传的文件, 若返回false或者返回Promise且被reject, 则停止上传。

function(file)

before-remove

删除文件之前的钩子, 参数为上传的文件和文件列表, 若返回false或者返回Promise且被reject, 则停止删除。

function(file, fileList)

list-type

文件列表的类型

string

text/picture/picture-card

text

auto-upload

是否在选取文件后立即进行上传

boolean

true

file-list

上传的文件列表, 例如: [{name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}]

array

[]

http-request

覆盖默认的上传行为, 可以自定义上传的实现

function

disabled

是否禁用

boolean

false

limit

最大允许上传个数

number

on-exceed

文件超出个数限制时的钩子

function(files, fileList)

1.3. Slot

name

说明

trigger

触发文件选择框的内容

tip

提示说明文字

1.4. Methods

方法名

说明

参数

clearFiles

清空已上传的文件列表(该方法不支持在before-upload中调用)

abort

取消上传请求

(file: fileList中的file对象)

submit

手动上传文件列表

2. Upload上传例子

2.1. 使用脚手架新建一个名为element-ui-upload的前端项目, 同时安装Element插件。

2.2. 编写index.js 

import Vue from 'vue'
import VueRouter from 'vue-router'
import UploadFunction from '../components/UploadFunction.vue'
import DragUpload from '../components/DragUpload.vue'
import ThumbnailUpload from '../components/ThumbnailUpload.vue'
import SubmitUpload from '../components/SubmitUpload.vue'

Vue.use(VueRouter)

const routes = [
  { path: '/', redirect: '/UploadFunction' },
  { path: '/UploadFunction', component: UploadFunction },
  { path: '/DragUpload', component: DragUpload },
  { path: '/ThumbnailUpload', component: ThumbnailUpload },
  { path: '/SubmitUpload', component: SubmitUpload }
]

const router = new VueRouter({
  routes
})

export default router

2.3. 在components在新建UploadFunction.vue

<template>
  <div>
    <h1>点击上传</h1>
    <h4>通过action设置上传的地址, 并且action必选参数。</h4>
    <h4>通过file-list上传的文件列表, 默认是[]数组。</h4>
    <h4>通过limit设置最大允许上传个数。</h4>
    <h4>通过list-type设置文件列表的类型, 可以设置为text/picture/picture-card, 默认是text。</h4>
    <h4>通过multiple设置是否支持多选文件。</h4>
    <h4>通过show-file-list设置是否显示已上传文件列表, 默认为true。</h4>
    <h4>通过accept设置接受上传的文件类型, 前端并没有绝对限制。</h4>
    <h4>before-upload上传文件之前的钩子, 参数为上传的文件, 若返回false或者返回Promise且被reject, 则停止上传。</h4>
    <h4>on-change文件状态改变时的钩子, 添加文件、上传成功和上传失败时都会被调用。</h4>
    <h4>on-progress文件上传时的钩子。</h4>
    <h4>on-success文件上传成功时的钩子。</h4>
    <h4>on-error文件上传失败时的钩子。</h4>
    <h4>on-preview点击文件列表中已上传的文件时的钩子。</h4>
    <h4>before-remove删除文件之前的钩子, 参数为上传的文件和文件列表, 若返回false或者返回Promise且被reject, 则停止删除。</h4>
    <h4>on-remove文件列表移除文件时的钩子。</h4>
    <h4>on-exceed文件超出个数限制时的钩子。</h4>
    <h4>通过slot你可以传入自定义的上传按钮类型和文字提示。</h4>
    <el-upload :action="action2" :file-list="fileList" :limit="limit" list-type="text" multiple :show-file-list="true" accept=".png, .jpg"
      :before-upload="handleBeforeUpload"
      :on-change="handleChange"
      :on-progress="handleProgress"
      :on-success="handleSuccess"
      :on-error="handleError"
      :on-preview="handlePreview"
      :before-remove="beforeRemove"
      :on-remove="handleRemove"
      :on-exceed="handleExceed">
      <el-button size="small" type="primary">点击上传</el-button>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png文件, 且不超过200MB。</div>
    </el-upload>
  </div>
</template>

<script>
export default {
  data () {
    return {
      action1: 'http://localhost:8080/ElementUIUpload/EUpload.action',
      action2: 'http://localhost:9876/upload',
      fileList: [],
      limit: 3
    }
  },
  methods: {
    handleBeforeUpload (file) {
      console.log('---handleBeforeUpload---')
      console.log(file)
    },
    handleChange (file, fileList) {
      console.log('---handleChange---')
      console.log(file)
      console.log(fileList)
    },
    handleProgress (event, file, fileList) {
      console.log('---handleProgress---')
      console.log(event)
      console.log(file)
      console.log(fileList)
    },
    handleSuccess (response, file, fileList) {
      console.log('---handleSuccess---')
      console.log(response)
      console.log(file)
      console.log(fileList)
    },
    handleError (err, file, fileList) {
      console.log('---handleError---')
      console.log(err)
      console.log(file)
      console.log(fileList)
    },
    handlePreview (file) {
      console.log('---handlePreview---')
      console.log(file)
    },
    beforeRemove (file, fileList) {
      console.log('---beforeRemove---')
      console.log(file)
      console.log(fileList)
      return this.$confirm(`确定移除 ${file.name}?`)
    },
    handleRemove (file, fileList) {
      console.log('---handleRemove---')
      console.log(file)
      console.log(fileList)
    },
    handleExceed (files, fileList) {
      console.log('---handleExceed---')
      console.log(files)
      console.log(fileList)
      this.$message.warning(`当前限制选择${this.limit}个文件, 本次选择了${files.length}个文件, 共选择了${files.length + fileList.length}个文件`)
    }
  }
}
</script>

2.4. 在components在新建DragUpload.vue

<template>
  <div>
    <h1>拖拽上传</h1>
    <h4>通过drag设置是否启用拖拽上传。</h4>
    <el-upload :action="action2" drag list-type="picture">
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">将文件拖到此处, 或<em>点击上传</em></div>
      <div class="el-upload__tip" slot="tip">只能上传jpg/png文件, 且不超过200MB。</div>
    </el-upload>
  </div>
</template>

<script>
export default {
  data () {
    return {
      action1: 'http://localhost:8080/ElementUIUpload/EUpload.action',
      action2: 'http://localhost:9876/upload'
    }
  }
}
</script>

2.5. 在components在新建ThumbnailUpload.vue

<template>
  <div>
    <h1>文件缩略图</h1>
    <h4>使用scoped-slot去设置缩略图模版。</h4>
    <el-upload :action="action2" list-type="picture-card" ref="upload">
      <i class="el-icon-plus"></i>
      <div slot="file" slot-scope="{file}">
        <img class="el-upload-list__item-thumbnail" :src="file.url" alt="">
        <span class="el-upload-list__item-actions">
          <span class="el-upload-list__item-preview" @click="handlePreview(file)"><i class="el-icon-zoom-in"></i></span>
          <span class="el-upload-list__item-delete" @click="handleRemove(file)"><i class="el-icon-delete"></i></span>
        </span>
      </div>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
  </div>
</template>

<script>
export default {
  data () {
    return {
      action1: 'http://localhost:8080/ElementUIUpload/EUpload.action',
      action2: 'http://localhost:9876/upload',
      dialogImageUrl: '',
      dialogVisible: false
    }
  },
  methods: {
    handlePreview (file) {
      this.dialogImageUrl = file.url
      this.dialogVisible = true
    },
    handleRemove (file) {
      var uploadFiles = this.$refs.upload.uploadFiles
      uploadFiles.filter(function (value, index, array) {
        if (value.uid === file.uid) {
          uploadFiles.splice(index, 1)
        }
      })
    }
  }
}
</script>

2.6. 在components在新建SubmitUpload.vue

<template>
  <div>
    <h1>手动上传</h1>
    <h4>auto-upload是否在选取文件后立即进行上传。</h4>
    <h4>trigger触发文件选择框的内容。</h4>
    <el-upload ref="upload" :action="action2" :auto-upload="false">
      <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
      <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png文件, 且不超过200MB。</div>
    </el-upload>
  </div>
</template>

<script>
export default {
  data () {
    return {
      action1: 'http://localhost:8080/ElementUIUpload/EUpload.action',
      action2: 'http://localhost:9876/upload'
    }
  },
  methods: {
    submitUpload () {
      this.$refs.upload.submit()
    }
  }
}
</script>

3. Servlet上传文件服务器

3.1. 新建一个名为ElementUIUpload动态web服务器项目

3.2. 新建UFilter.java, 设置跨域访问 

package com.bjbs;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

public class UFilter implements Filter {
  @Override
  public void init(FilterConfig config) throws ServletException {
    System.out.println("在服务器加载项目的时候创建, 初始化。");
  }
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    System.out.println("进入到过滤器了, 可以进行过滤操作了。");
    // 本过滤器放行, 你可以去下一个过滤器或者Servlet了
    chain.doFilter(request, response);
    
    HttpServletResponse res = (HttpServletResponse) response;
    // 设置跨域访问
    /* 允许跨域的主机地址 */
    res.setHeader("Access-Control-Allow-Origin", "*");
    /* 允许跨域的请求方法GET, POST, HEAD 等 */
    res.setHeader("Access-Control-Allow-Methods", "*");
    /* 重新预检验跨域的缓存时间 (s) */
    res.setHeader("Access-Control-Max-Age", "4200");
    /* 允许跨域的请求头 */
    res.setHeader("Access-Control-Allow-Headers", "*");
    /* 是否携带cookie */
    res.setHeader("Access-Control-Allow-Credentials", "true");
  }
  @Override
  public void destroy() {
    System.out.println("服务器停止或者移除项目的时候的销毁。");
  }
}

3.3. 新建EUpload.java上传文件

package com.bjbs;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;

public class EUpload extends HttpServlet {
  private static final long serialVersionUID = 1L;

  // 上传文件存储目录
  private static final String UPLOAD_DIRECTORY = "upload";
  // 上传配置
  private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3; // 3MB
  private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB
  private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB

  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 检测是否为多媒体上传
    if (!ServletFileUpload.isMultipartContent(req)) {
      // 如果不是则停止
      PrintWriter writer = resp.getWriter();
      writer.println("Error: 表单必须包含 enctype=multipart/form-data");
      writer.flush();
      return;
    }

    // 配置上传参数
    DiskFileItemFactory factory = new DiskFileItemFactory();
    // 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
    factory.setSizeThreshold(MEMORY_THRESHOLD);
    // 设置临时存储目录
    factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

    ServletFileUpload upload = new ServletFileUpload(factory);
    // 设置最大文件上传值
    upload.setFileSizeMax(MAX_FILE_SIZE);
    // 设置最大请求值 (包含文件和表单数据)
    upload.setSizeMax(MAX_REQUEST_SIZE);
    // 中文处理
    upload.setHeaderEncoding("UTF-8");

    // 构造临时路径来存储上传的文件
    // 这个路径相对当前应用的目录
    String uploadPath = req.getServletContext().getRealPath("./") + File.separator + UPLOAD_DIRECTORY;
    // 如果目录不存在则创建
    File uploadDir = new File(uploadPath);
    if (!uploadDir.exists()) {
      uploadDir.mkdir();
    }

    String msg = "上传文件失败";
    try {
      // 解析请求的内容提取文件数据
      List<FileItem> formItems = upload.parseRequest(new ServletRequestContext(req));
      if (formItems != null && formItems.size() > 0) {
        // 迭代表单数据
        for (FileItem item : formItems) {
          // 处理不在表单中的字段
          if (!item.isFormField()) {
            String fileName = new File(item.getName()).getName();
            String filePath = uploadPath + File.separator + fileName;
            File storeFile = new File(filePath);
            // 在控制台输出文件的上传路径
            System.out.println(filePath);
            // 保存文件到硬盘
            item.write(storeFile);
          }
        }
        
        msg = "文件上传成功";
      }
    } catch (Exception ex) {
      msg = ex.getMessage();
    }
    
    // 不管是字节流还是字符流, 直接使用一行代码就可以解决响应乱码问题。
    resp.setContentType("text/html;charset=UTF-8");
    resp.getWriter().print(msg);
  }

  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req, resp);
  }
}

3.4. 在web.xml中, 配置过滤器和Servlet

3.5. 新建index.html, 使用vue和element-ui, 使用upload组件 

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>上传文件</title>
    <!-- 引入样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入Vue -->
      <script src="https://lib.baomitu.com/vue/2.6.14/vue.common.dev.js"></script>
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  </head>
  <body>
    <div id="app">
      <el-upload action="http://localhost:9876/upload" :file-list="fileList" :on-success="handleSuccess" :on-error="handleError">
          <el-button size="small" type="primary">点击上传</el-button>
        </el-upload>
    </div>
    
    <script>
      new Vue({
          el: '#app',
          data: {
            fileList: []
          },
          methods: {
            handleSuccess (response, file, fileList) {
              console.log('---handleSuccess---')
              console.log(response)
              console.log(file)
                console.log(fileList)
            },
            handleError (err, file, fileList) {
              console.log('---handleError---')
                console.log(err)
              console.log(file)
                console.log(fileList)
            }
          }
        })
    </script>
  </body>
</html>

4. SpringBoot上传文件服务器

4.1. 新建一个名为element-upload-spring-boot的SpringBoot项目

4.2. 配置pom.xml 

<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  
  <modelVersion>4.0.0</modelVersion>
  
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.13.RELEASE</version>
  </parent>
  
  <groupId>com.bjbs</groupId>
  <artifactId>element-upload-spring-boot</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  
  <properties>
    <!-- 修改jdk版本 -->
    <java.version>1.8</java.version>
    <!-- 指定thymeleaf和thymeleaf-layout-dialect高版本可以防止html标签不规范报错 -->
    <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
    <thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>
  </properties>
  
  <dependencies>
    <!-- springBoot的启动器 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- thymeleaf的启动器 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
  </dependencies>
  
</project>

4.3. 新建CorsConfig.java, 支持跨域访问

package com.bjbs.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**").allowedOrigins("*").allowCredentials(true)
        .allowedMethods("GET", "POST", "DELETE", "PUT").maxAge(3600);
  }
}

4.4. 新建UploadController.java

package com.bjbs.controller;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

@RestController
public class UploadController {
  @RequestMapping(value="/upload")
  public Map<String, Object> upload(HttpServletRequest req) {
    Map<String, Object> map = new HashMap<String, Object>();

    // 构造临时路径来存储上传的文件
    // 这个路径相对当前应用的目录
    String uploadPath = req.getServletContext().getRealPath("./") + File.separator + "upload";
    // 如果目录不存在则创建
    File file = new File(uploadPath);
    if (!file.exists()) {
      file.mkdir();
    }
    
    MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) req;
    Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
      for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
          MultipartFile multipartFile = entry.getValue();
          String fileName = multipartFile.getOriginalFilename();
          String filePath = uploadPath + File.separator + fileName;
          try {
        multipartFile.transferTo(new File(filePath));
        map.put(fileName, filePath);
      } catch (IllegalStateException | IOException e) {
        e.printStackTrace();
        map.put("msg", e.getMessage());
        return map;
      }
      }
    
    map.put("msg", "success");
    return map;
  }
}

4.5. 新建App.java

package com.bjbs;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
  public static void main(String[] args) {
    SpringApplication.run(App.class, args);
  }
}

4.6. 在src/main/resources下, 配置application.properties

server.port=9876
#设置单个上传文件的大小
spring.http.multipart.maxFileSize=200MB
#设置一次请求上传文件的总容量
spring.http.multipart.maxRequestSize=1000MB

4.7. 在src/main/resources下, 新建static文件夹, 在static文件夹下新建index.html, 使用vue和element-ui, 使用upload组件

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>上传文件</title>
    <!-- 引入样式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入Vue -->
      <script src="https://lib.baomitu.com/vue/2.6.14/vue.common.dev.js"></script>
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  </head>
  <body>
    <div id="app">
      <el-upload action="http://localhost:9876/upload" :file-list="fileList" :on-success="handleSuccess" :on-error="handleError">
          <el-button size="small" type="primary">点击上传</el-button>
        </el-upload>
    </div>
    
    <script>
      new Vue({
          el: '#app',
          data: {
            fileList: []
          },
          methods: {
            handleSuccess (response, file, fileList) {
              console.log('---handleSuccess---')
              console.log(response)
              console.log(file)
                console.log(fileList)
            },
            handleError (err, file, fileList) {
              console.log('---handleError---')
                console.log(err)
              console.log(file)
                console.log(fileList)
            }
          }
        })
    </script>
  </body>
</html>

5. 允许项目, 上传文件

5.1. 启动名为element-upload-spring-boot的SpringBoot项目

5.2. 启动前端element-ui-upload, 访问http://localhost:8080/#/UploadFunction, 上传图片 

5.3. 前端访问http://localhost:8080/#/DragUpload, 拖拽上传图片 

5.4. 前端访问http://localhost:8080/#/ThumbnailUpload, 上传图片查看大图 

5.5. 前端访问http://localhost:8080/#/SubmitUpload, 手动上传图片 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值