Element+vue+分页+七牛云实现图片上传

    科技2025-11-01  8

    目录

    0.准备1.vue安装所需环境2.main.js中导包3.index.vue页面4.insert.vue页面5.后端:上传工具类6.后端:上传Controller7.后端:分页实体类,serviceImpl和controller

    0.准备

    注册并实名七牛云

    1.vue安装所需环境

    npm i element-ui -S

    pom依赖:

    <dependency> <groupId>com.qiniu</groupId> <artifactId>qiniu-java-sdk</artifactId> <version>[7.3.0, 7.3.99]</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> <scope>compile</scope> </dependency>

    2.main.js中导包

    import Vue from 'vue' import App from './App' import router from './router' import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI); Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' })

    3.index.vue页面

    <template> <div> <el-container style="height: 500px; border: 1px solid #eee"> <el-aside width="200px" style="background-color: rgb(238, 241, 246)"> <el-menu :default-openeds="['1', '3']"> <el-submenu index="1"> <template slot="title"><i class="el-icon-message"></i>导航一</template> <el-menu-item-group> <template slot="title">分组一</template> <el-menu-item index="1-1">选项1</el-menu-item> <el-menu-item index="1-2">选项2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="分组2"> <el-menu-item index="1-3">选项3</el-menu-item> </el-menu-item-group> <el-submenu index="1-4"> <template slot="title">选项4</template> <el-menu-item index="1-4-1">选项4-1</el-menu-item> </el-submenu> </el-submenu> <el-submenu index="2"> <template slot="title"><i class="el-icon-menu"></i>导航二</template> <el-menu-item-group> <template slot="title">分组一</template> <el-menu-item index="2-1">选项1</el-menu-item> <el-menu-item index="2-2">选项2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="分组2"> <el-menu-item index="2-3">选项3</el-menu-item> </el-menu-item-group> <el-submenu index="2-4"> <template slot="title">选项4</template> <el-menu-item index="2-4-1">选项4-1</el-menu-item> </el-submenu> </el-submenu> <el-submenu index="3"> <template slot="title"><i class="el-icon-setting"></i>导航三</template> <el-menu-item-group> <template slot="title">分组一</template> <el-menu-item index="3-1">选项1</el-menu-item> <el-menu-item index="3-2">选项2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="分组2"> <el-menu-item index="3-3">选项3</el-menu-item> </el-menu-item-group> <el-submenu index="3-4"> <template slot="title">选项4</template> <el-menu-item index="3-4-1">选项4-1</el-menu-item> </el-submenu> </el-submenu> </el-menu> </el-aside> <el-container> <el-header style="text-align: right; font-size: 12px"> <el-dropdown> <i class="el-icon-setting" style="margin-right: 15px"></i> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>查看</el-dropdown-item> <el-dropdown-item>新增</el-dropdown-item> <el-dropdown-item>删除</el-dropdown-item> </el-dropdown-menu> </el-dropdown> <span>王小虎</span> </el-header> <el-main> <el-button type="success" icon="el-icon-check" @click="insertBook" circle></el-button> <el-table :data="tableData"> <el-table-column prop="bookName" label="书名" width="140"></el-table-column> <el-table-column prop="url" label="图片" width="140"> <template slot-scope="scope"> <el-image style="width: 60px; height: 60px" :src="scope.row.url" fit="fill"></el-image> </template> </el-table-column> <el-table-column prop="price" label="价格" width="120"></el-table-column> <el-table-column prop="createtime" label="发布日期" width="140"></el-table-column> <el-table-column prop="author" label="作者"></el-table-column> <el-table-column fixed="right" label="操作" width="100"> <template slot-scope="scope"> <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button> <el-button type="text" size="small">编辑</el-button> </template> </el-table-column> </el-table> <div class="block"> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="this.params.page" :page-sizes="[1, 2, 3, 4]" :page-size="this.params.size" layout="total, sizes, prev, pager, next, jumper" :total=this.total> </el-pagination> </div> </el-main> </el-container> </el-container> </div> </template> <script> import axios from 'axios' export default { data() { return { tableData: [], total:10, params: { size:10, page:1, } } }, methods: { handleClick(row) { this.$router.push({name:"insert",params:{id:row.id}}) }, findAll:function () { axios.get("api/findAll/"+this.params.page+"/"+this.params.size).then(res=>{ this.tableData=res.data.list; this.total=res.data.total; }) },insertBook:function(){ this.$router.push("/insert") }, //分页 handleSizeChange(val) { console.log(`每页 ${val} 条`); this.params.size=val; this.findAll(); }, handleCurrentChange(val) { console.log(`当前页: ${val}`); this.params.page=val; this.findAll(); } }, mounted(){ this.findAll(); } }; </script> <style> .el-header { background-color: #B3C0D1; color: #333; line-height: 60px; } .el-aside { color: #333; } </style>

    4.insert.vue页面

    <template> <div> <el-form ref="form" :model="form" :rules="rules" label-width="80px"> <el-form-item label="书名" prop="bookName"> <el-input v-model="form.bookName"></el-input> </el-form-item> <el-form-item label="图片" prop="url"> <el-upload class="avatar-uploader" action="api/upload/" v-if="this.form.url==null" :show-file-list="false" :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload"> <img v-if="imageUrl" :src="imageUrl" class="avatar"> <i v-else class="el-icon-plus avatar-uploader-icon"></i> </el-upload> <el-image style="width: 100px; height: 100px" v-if="this.form.url!=null" :src="this.form.url" fit="fill"></el-image> </el-form-item> <el-form-item label="价格" prop="price"> <el-input v-model="form.price"></el-input> </el-form-item> <el-form-item label="出版日期" prop="createtime"> <el-col :span="11"> <el-date-picker type="date" placeholder="选择日期" v-model="form.createtime" style="width: 100%;"></el-date-picker> </el-col> </el-form-item><el-form-item label="作者" prop="author"> <el-input v-model="form.author"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="onSubmit('form')">立即创建</el-button> <el-button>取消</el-button> </el-form-item> </el-form> </div> </template> <script> import axios from 'axios' export default { data() { return { form: { }, imageUrl: '', rules:{ bookName: [ { required: true, message: '请输入书名', trigger: 'blur' }, { min: 3, max: 30, message: '长度在 3 到 30 个字符', trigger: 'blur' } ],url:[ { required: true, message: '上传图片', trigger: 'chang' }, ],price:[ { required: true, message: '请填写价格', trigger: 'blur' }, ],createtime:[ { type: 'date', required: true, message: '请选择时间', trigger: 'change' } ],author:[ { required: true, message: '请输入作者', trigger: 'blur' }, ] } } }, methods: { onSubmit(formName) { console.log(this.form); this.$refs[formName].validate((valid) => { if (valid) { axios.post("api/saveOrUpdate",this.form).then(res=>{ if(res.data="success"){ this.$router.push("/") } }) } else { console.log('error submit!!'); return false; } }); }, findById(id){ axios.post("api/findById",{id:id}).then(res=>{ this.form=res.data; }) }, handleAvatarSuccess(res, file) { this.imageUrl = URL.createObjectURL(file.raw) this.form.url=res; }, beforeAvatarUpload(file) { const isJPG = file.type === 'image/jpeg'; const isLt2M = file.size / 1024 / 1024 < 2; if (!isJPG) { this.$message.error('上传头像图片只能是 JPG 格式!'); } if (!isLt2M) { this.$message.error('上传头像图片大小不能超过 2MB!'); } return isJPG && isLt2M; } }, mounted(){ var id=this.$route.params.id; if(id!=undefined){ this.findById(id) } } } </script> <style> .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; } </style>

    5.后端:上传工具类

    public class UploadUtils { public String upload(MultipartFile multipartFile){ //构造一个带指定 Region 对象的配置类 Configuration cfg = new Configuration(Region.region0()); //...其他参数参考类注释 UploadManager uploadManager = new UploadManager(cfg); //...生成上传凭证,然后准备上传 String accessKey = "自己的ak"; String secretKey = "自己的sk"; String bucket = "自己的名称"; //默认不指定key的情况下,以文件内容的hash值作为文件名 String key = null; try { byte[] bytes = multipartFile.getBytes(); ByteArrayInputStream byteInputStream=new ByteArrayInputStream(bytes); Auth auth = Auth.create(accessKey, secretKey); String upToken = auth.uploadToken(bucket); try { Response response = uploadManager.put(byteInputStream,key,upToken,null, null); //解析上传成功的结果 DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class); System.out.println(putRet.key); System.out.println(putRet.hash); return "自己的网址"+putRet.key; } catch (QiniuException ex) { Response r = ex.response; System.err.println(r.toString()); try { System.err.println(r.bodyString()); } catch (QiniuException ex2) { //ignore } } } catch (UnsupportedEncodingException ex) { //ignore } catch (IOException e) { e.printStackTrace(); } return ""; } }

    6.后端:上传Controller

    @RequestMapping("/upload") public String upload(@RequestParam("file") MultipartFile multipartFile){ System.out.println(multipartFile.getOriginalFilename()); UploadUtils uploadUtils = new UploadUtils(); String upload = uploadUtils.upload(multipartFile); return upload; }

    7.后端:分页实体类,serviceImpl和controller

    实体类

    @Data public class BookResp<T> { public List<T> list; public Long total; }

    serviceImpl

    @Override public BookResp findAll(Integer page, Integer size) { PageRequest pageRequest = new PageRequest(page, size); BookResp bookResp = new BookResp<>(); Page<Book> all = bookRespository.findAll(pageRequest); if(all!=null){ List<Book> content = all.getContent(); bookResp.setList(content); long totalElements = all.getTotalElements(); bookResp.setTotal(totalElements); return bookResp; } return null; }

    controller

    @RequestMapping("/findAll/{page}/{size}") public BookResp findAll(@PathVariable("page")Integer page,@PathVariable("size") Integer size){ BookResp bookResp=bookservice.findAll(page-1,size); return bookResp; }

    效果图:

    Processed: 0.021, SQL: 8