ElementUI之Upload 上传的使用
文章目录
- 说明
- SSM使用
- 引入依赖
- 在spring-mvc.xml中加入配置
- 创建上传工具类AliOssUtil
- 响应工具类ResultJSON
- 编写controller
- 自动上传
- 代码编写
- 结果如下演示
- 手动上传
- 前端代码编写
- 后端代码编写
- 结果演示如下
说明
为了方便演示,前后端代码一起写了
关于对象存储请看我另一篇博客
阿里云对象存储OSS的使用
SSM使用
引入依赖
<!--阿里云OSS依赖--><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.17.4</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version></dependency><dependency><groupId>javax.activation</groupId><artifactId>activation</artifactId><version>1.1.1</version></dependency><!-- no more than 2.3.3--><dependency><groupId>org.glassfish.jaxb</groupId><artifactId>jaxb-runtime</artifactId><version>2.3.3</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency>
在spring-mvc.xml中加入配置
<!-- 配置 MultipartResolver 用于文件上传 --><bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"><!-- 设置最大上传文件大小 --><property name="maxUploadSize" value="10485760"/> <!-- 10MB --><property name="maxInMemorySize" value="4096"/><property name="defaultEncoding" value="UTF-8"/></bean>
创建上传工具类AliOssUtil
package com.Teenage_education_network.utils;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;import java.io.InputStream;public class AliOssUtil {private static final String ENDPOINT = "https://oss-cn-beijing.aliyuncs.com";private static final String ACCESS_KEY_ID = "你的id";private static final String SECRET_ACCESS_KEY = "你的秘钥";private static final String BUCKET_NAME = "项目名";/** uploadFile方法* objectName:文件名称比如 "YEjdihp893bif1.jpg"* inputStream:文件流,用于读取文件比如,D:\Users\Administrator\Desktop\YEjdihp893bif1.jpg* *///上传文件,返回文件的公网访问地址public static String uploadFile(String objectName, InputStream inputStream){// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(ENDPOINT,ACCESS_KEY_ID,SECRET_ACCESS_KEY);//公文访问地址String url = "";try {// 创建存储空间。ossClient.createBucket(BUCKET_NAME);ossClient.putObject(BUCKET_NAME, objectName, inputStream);// 这里是返回阿里云的url地址url = "https://"+BUCKET_NAME+"."+ENDPOINT.substring(ENDPOINT.lastIndexOf("/")+1)+"/"+objectName;} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}return url;}
}
响应工具类ResultJSON
package com.hsh.pojo.tdo;import java.io.Serializable;/*** @Author: wzy* @Date: 2024/11/13 11:03* @Description: 返回结果类*/
public class ResultJSON<T> implements Serializable {private Integer code;private String msg;private T data;public ResultJSON(Integer code, String msg, T data) {this.code = code;this.msg = msg;this.data = data;}/*** 操作成功或者失败* @param c 受影响行数* @return 当前传入的受影响行数>0则返回成功,否则返回失败*/public static ResultJSON successORerror(int c){return c>0?new ResultJSON(200,"操作成功",c):new ResultJSON(400,"操作失败",c);}public static ResultJSON success(){return new ResultJSON(200,"操作成功",null);}public static ResultJSON success(String msg){return new ResultJSON(200,msg,null);}public static <T> ResultJSON success(T data){return new ResultJSON(200,"操作成功",data);}public static ResultJSON success(Integer code,String msg){return new ResultJSON(code,msg,null);}public static <T> ResultJSON success(String msg,T data){return new ResultJSON(200,msg,data);}public static <T> ResultJSON success(Integer code,String msg,T data){return new ResultJSON(code,msg,data);}public static ResultJSON error(){return new ResultJSON(500,"操作失败",null);}public static ResultJSON error(String msg){return new ResultJSON(500,msg,null);}public static ResultJSON error(Integer code,String msg){return new ResultJSON(code,msg,null);}public T getData() {return data;}public void setData(T data) {this.data = data;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}
}
编写controller
package com.hsh.controller;import com.hsh.pojo.tdo.ResultJSON;
import com.hsh.utils.AliOssUtil;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.UUID;/*** @author xrkhy* @date 2025/9/6 19:05* @description*/@RestController
@RequestMapping("/upload")
public class UploadController {// 本次请求通过elementPlus的el-upload组件上传图片,通过el-upload组件的属性发起请求// 前端上传路径action="/api/upload/imgUpload" 要和后端一致 这里的/api是前端的反向代理的标识// 前端的name="img" 是这里的形参名// 前端的请求头添加token :headers="{'Authorization':tokenStore.token}"@PostMapping("/imgUpload")public ResultJSON<String> imgUpload(@RequestParam("img") MultipartFile img) throws IOException {System.out.println(img);if (img == null || img.isEmpty()) {// 处理文件为空的情况return ResultJSON.error("文件不能为空");}String originalFilename = img.getOriginalFilename();// 生成新的唯一的文件名String fileNmae = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));String url = AliOssUtil.uploadFile(fileNmae, img.getInputStream());System.out.println(url);return ResultJSON.success("添加成功",url);}
}
自动上传
代码编写
<template><el-form:model="productForm"label-width="120px"label-position="right"><!-- 用户基础信息 --><el-form-item label="商品名称" prop="productName"><el-input v-model="productForm.productName"></el-input></el-form-item><el-form-item label="封面图片"><!-- :auto-upload 设置是否自动上传 true自动上传 --><!-- action为你的请求路径:你要替换为你的上传API地址 --><!-- name: 上传的文件字段名 (也就是后端的参数 我这里是img)后端的接收参数如下就是我上面写的UploadControllerpublic ResultJSON<String> imgUpload(@RequestParam("img") MultipartFile img){}--><!-- :on-success="handleAvatarSuccess" 上传成功回调 --><!-- :before-upload="beforeAvatarUpload"上传前校验 --><!-- list-type="picture-card" 文件列表的类型 这里不需要因为已经有<i class="el-icon-plus" v-if="!productForm.imageUrl"></i>代替了--><!-- :show-file-list="false" 是否显示已上传文件列表 --><!-- 除了上面还可以设置响应头,配置如下:headers="{'Authorization':tokenStore.token}"--><el-upload:auto-upload="true"action="http://localhost:8080/upload/imgUpload"name="img":on-success="handleAvatarSuccess":before-upload="beforeAvatarUpload":show-file-list="false"><!-- v-if="!productForm.imageUrl" 是如果上传成功这个+图标(<i class="el-icon-plus"></i>)上传的提示就不显示了 --><istyle="font-size: 20px; border: 1px solid #ccc; padding: 20px"class="el-icon-plus"v-if="!productForm.imageUrl"></i><img style="width: 100px" v-else :src="productForm.imageUrl" /></el-upload></el-form-item><el-form-item label="商品价格" prop="productPrice"><el-input-numberv-model="productForm.productPrice":precision="2":step="0.01"></el-input-number></el-form-item><el-form-item label="商品库存" prop="productStock"><el-input-numberv-model="productForm.productStock"label="描述文字"></el-input-number></el-form-item><!-- 操作按钮 --><el-form-item><el-button type="primary" @click="submitForm">提交</el-button><el-button @click="resetForm">重置</el-button></el-form-item></el-form>
</template><script>
export default {data() {return {productForm: {productId: null,productName: "",imageUrl: "",productPrice: "",productStock: ""},}}methods: {// 上传成功后的回调handleAvatarSuccess(res, file) {this.productForm.imageUrl = res.data;},// 上传前的校验beforeAvatarUpload(file) {const isJPG = file.type === "image/jpeg" || file.type === "image/png";const isLt2M = file.size / 1024 / 1024 < 2;if (!isJPG) {this.$message.error("上传头像图片只能是 JPG 或 PNG 格式!");}if (!isLt2M) {this.$message.error("上传头像图片大小不能超过 2MB!");}return isJPG && isLt2M;},submitForm() {console.log("提交的数据:", this.formData);// 这里在发起请求},}
}
</script>
结果如下演示
上面数据确实是拿到了,此时在点击提交发送。
手动上传
前端代码编写
<template><div><h1>图片手动提交</h1><el-form:model="productForm"style="width: 500px"label-width="120px"label-position="right"><!-- 用户基础信息 --><el-form-item label="商品名称" prop="productName"><el-input v-model="productForm.productName"></el-input></el-form-item><el-form-item label="封面图片"><!-- :auto-upload 设置是否自动上传 true自动上传 --><!-- action为你的请求路径:你要替换为你的上传API地址 --><!-- list-type="picture-card" 文件列表的类型 这里不需要因为已经有<i class="el-icon-plus" v-if="!productForm.imageUrl"></i>代替了--><!-- :show-file-list="false" 是否显示已上传文件列表 这里关闭 --><!-- v-if="!productForm.imageUrl" 是如果上传成功这个+图标(<i class="el-icon-plus"></i>)上传的提示就不显示了 --><el-upload:auto-upload="false"action="#":show-file-list="false":on-change="handleImgChange"><istyle="font-size: 20px; border: 1px solid #ccc; padding: 20px"class="el-icon-plus"v-if="!productForm.imageUrl"></i><img style="width: 100px" v-else :src="productForm.imageUrl" /></el-upload><!-- v-if="productForm.imageUrl" 如果图片不存在 img不显示 --><!-- <img v-if="imgURL" :src="imgURL" /> --></el-form-item><el-form-item label="商品价格" prop="productPrice"><el-input-numberv-model="productForm.productPrice":precision="2":step="0.01"></el-input-number></el-form-item><el-form-item label="商品库存" prop="productStock"><el-input-numberv-model="productForm.productStock"label="描述文字"></el-input-number></el-form-item><!-- 操作按钮 --><el-form-item><el-button type="primary" @click="submitForm">提交</el-button></el-form-item></el-form></div>
</template><script>
import axios from "axios";export default {name: "ImageUpload",data() {return {// 表单数据// 注意这里表单不能有字段为null,否则会报错// 比如productId: null, 发送给后端报错productForm: {productId: "",productName: "",imageUrl: "",productPrice: "",productStock: "",imgUrlFile: ""}};},methods: {// handleFileChange(file, fileList) {// this.fileList = fileList;// },// 提交前实现封面图片预览handleImgChange(uploadFile) {// 预览图片// this.imgUrl = URL.createObjectURL(uploadFile.raw);this.productForm.imageUrl = URL.createObjectURL(uploadFile.raw);console.log(this.productForm.imageUrl);this.productForm.imgUrlFile = uploadFile.raw;// this.productForm.imageUrl = uploadFile.raw;},async submitForm() {const formData = new FormData();// 追加其他表单字段// 遍历 productForm 对象的属性for (const key in this.productForm) {// 将每个属性和值添加到 FormData 中formData.append(key, this.productForm[key]);}// 追加文件字段formData.append("file", this.imgUrlFile);this.clgFromData(formData);const res = await axios.post("http://localhost:8080/product/addProductWithImg",formData// 下面的headers可以不,会自动识别是json还是formdata// {// headers: {// "Content-Type": "multipart/form-data"// }// });console.log(res);},clgFromData(formData) {for (let pair of formData.entries()) {console.log(pair[0] + ", " + pair[1]);}}}
};
</script><style scoped></style>
后端代码编写
package com.hsh.controller;import com.hsh.pojo.Product;
import com.hsh.pojo.tdo.ResultJSON;
import com.hsh.service.ProductService;
import com.hsh.utils.AliOssUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.util.List;
import java.util.UUID;@RestController
@RequestMapping("/product")
@CrossOrigin(origins = "http://localhost:8081")
public class ProductController {@AutowiredProductService productService;@PostMapping("/addProduct")public ResultJSON addProduct(@RequestBody Product product){System.out.println("product = " + product);return productService.addProduct(product);}// 注意 传入的product对象的属性不能是 null 也不能是 MultipartFile,否则报400的错误// 注意:java的product对象中,没有imgUrlFile属性。// 前端传入的product对象中,imgUrlFile属性是MultipartFile类型。@PostMapping("/addProductWithImg")public ResultJSON<Product> findProductById(@ModelAttribute Product product,@RequestParam(value = "imgUrlFile",required = false) MultipartFile imgUrlFile) throws IOException {System.out.println("product = " + product);System.out.println("imgFile = " + imgUrlFile);if (imgUrlFile == null || imgUrlFile.isEmpty()) {// 处理文件为空的情况return ResultJSON.error("文件不能为空");}String originalFilename = imgUrlFile.getOriginalFilename();// 生成新的唯一的文件名String fileNmae = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));String url = AliOssUtil.uploadFile(fileNmae, imgUrlFile.getInputStream());System.out.println(url);product.setImageUrl(url);return productService.addProduct(product);}}