文章目录

  • 1.单体前后端项目上传
    • 1.上传流程
    • 2. BuckName 和EndPoint
    • 3. AccessKey 和Access Secret(创建RAM(Resource Access Manage)的子账号,然后可以获得Accesskey和Acess Secret)
    • 3.根据创建的子账号分配OSS的所有权限(可以对文件进行上传,下载,删除的权限)
    • 4.采用上传的方式(服务器直传,服务器得签名后后端直传,前端直传)
    • 5. 出现跨域问题解决
    • 引入依赖
    • 6.前端实现code
      • 6.1 单个文件上传
        • 可以用一个url变量接收我们的上传之后成功的图片路径,点击保存的时间可以将这个url传到数据库中去,前端在直接通过单向绑定:src ="显示数据库中保存的url"
      • 6.2多个文件上传
    • 7.后端code实现
  • 2.SpringCloud形式OSS上传
    • 1.引入依赖
    • 2.后端实现code
    • 3.前端实现code
  • 2. 商品管理系统OSS实现图片显示和图片上传
    • 1.前端Code
    • 1.后端Code

1.单体前后端项目上传

1.上传流程


这样有利于保护自己的账号和密码不被泄露,通过账号密码生成的防伪笔名进行验证是否正确

2. BuckName 和EndPoint

3. AccessKey 和Access Secret(创建RAM(Resource Access Manage)的子账号,然后可以获得Accesskey和Acess Secret)


3.根据创建的子账号分配OSS的所有权限(可以对文件进行上传,下载,删除的权限)

4.采用上传的方式(服务器直传,服务器得签名后后端直传,前端直传)

前端直传:不好,用户可以直接f12找到我们的endpoint,bucketName,和重要的Acesskey,AccessSecret,不安全,导致我们的信息泄露。
服务器直传:会造成性能瓶颈,给服务器造成压力。
服务器得签名后后端直传:这种方法可以,可以加密我们的签名之后进行上传。如果想了解用户上传了什么东西可以设计 上传回调

5. 出现跨域问题解决

引入依赖

    <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.15.0</version></dependency><dependency>

6.前端实现code

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>oss测试上传</title><script src="static/js/vue.min.js"></script><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"><!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script></head>
<body><div id="app"><!-- <form action="/upload/oss" method="post" enctype="multipart/form-data"><input type="file" name="file" value="选择文件上传"><input type="submit" name="提交"/></form> --><el-uploaddraggable="true"class="upload-demo":action="obj.host":before-upload="ossPolicy":on-success="onsuccess"//上传时绑定的数据:data="obj":limit="2":file-list="fileList"list-type="picture"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload></div><script src="static/js/axios.min.js"></script>
<script type="text/javascript ">var vm=new Vue({el:"#app",data:{fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}],obj:{OSSAccessKeyId:"",policy:"",signature:"",key:"",host:"",dir:"",}},methods: {ossPolicy(file){// 上传前,获取服务器给的签名axios({url:"http://localhost:8080/oss/policy",method:"get",}).then(res=>{console.log("come in ---------",res.data)this.obj.OSSAccessKeyId = res.data.accessId;this.obj.policy = res.data.policy;this.obj.dir = res.data.dir;this.obj.signature = res.data.signature; //传到oss的服务器地址this.obj.host = res.data.host;this.obj.key =res.data.dir + "${filename}";})},//文件上传成功时调用onsuccess(response, file, fileList){console.log("response",response)console.log(file)},}})
</script></body>
</html>

6.1 单个文件上传

<template> <div><el-upload:action="dataObj.host":data="dataObj"list-type="picture":multiple="false" :show-file-list="showFileList":file-list="fileList":before-upload="beforeUpload":on-remove="handleRemove":on-success="handleUploadSuccess":on-preview="handlePreview"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过10MB</div></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="fileList[0].url" alt=""></el-dialog></div>
</template>
<script>import {policy} from './policy'import { getUUID } from '@/utils'export default {name: 'singleUpload',props: {value: String},computed: {imageUrl() {return this.value;},imageName() {if (this.value != null && this.value !== '') {return this.value.substr(this.value.lastIndexOf("/") + 1);} else {return null;}},fileList() {return [{name: this.imageName,url: this.imageUrl}]},showFileList: {get: function () {return this.value !== null && this.value !== ''&& this.value!==undefined;},set: function (newValue) {}}},data() {return {dataObj: {policy: '',signature: '',key: '',ossaccessKeyId: '',dir: '',host: '',// callback:'',},dialogVisible: false,url:'',};},methods: {emitInput(val) {this.$emit('input', val)},handleRemove(file, fileList) {this.emitInput('');},handlePreview(file) {this.dialogVisible = true;},beforeUpload(file) {let _self = this;return new Promise((resolve, reject) => {policy().then(response => {console.log("响应的数据",response);_self.dataObj.policy = response.data.policy;_self.dataObj.signature = response.data.signature;_self.dataObj.ossaccessKeyId = response.data.accessid;_self.dataObj.key = response.data.dir +getUUID()+'_${filename}';_self.dataObj.dir = response.data.dir;_self.dataObj.host = response.data.host;console.log("响应的数据222。。。",_self.dataObj);resolve(true)}).catch(err => {reject(false)})})},handleUploadSuccess(res, file) {console.log("上传成功...")this.showFileList = true;this.fileList.pop();this.fileList.push({name: file.name, url: this.dataObj.host + '/' + this.dataObj.key.replace("${filename}",file.name) });this.url = this.fileList[0].url;this.emitInput(this.fileList[0].url);}}}
</script>
<style></style>
可以用一个url变量接收我们的上传之后成功的图片路径,点击保存的时间可以将这个url传到数据库中去,前端在直接通过单向绑定:src =“显示数据库中保存的url”

6.2多个文件上传

<template><div><el-uploadaction="http://+`你的bucketName` + '.' +'你的endpoint'":data="dataObj":list-type="listType":file-list="fileList":before-upload="beforeUpload":on-remove="handleRemove":on-success="handleUploadSuccess":on-preview="handlePreview":limit="maxCount":on-exceed="handleExceed":show-file-list="showFile"><i class="el-icon-plus"></i></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="dialogImageUrl" alt /></el-dialog></div>
</template>
<script>
import { policy } from "./policy";
import { getUUID } from '@/utils'
export default {name: "multiUpload",props: {//图片属性数组value: Array,//最大上传图片数量maxCount: {type: Number,default: 30},listType:{type: String,default: "picture-card"},showFile:{type: Boolean,default: true}},data() {return {dataObj: {policy: "",signature: "",key: "",ossaccessKeyId: "",dir: "",host: "",uuid: ""},dialogVisible: false,dialogImageUrl: null};},computed: {fileList() {let fileList = [];for (let i = 0; i < this.value.length; i++) {fileList.push({ url: this.value[i] });}return fileList;}},mounted() {},methods: {emitInput(fileList) {let value = [];for (let i = 0; i < fileList.length; i++) {value.push(fileList[i].url);}this.$emit("input", value);},handleRemove(file, fileList) {this.emitInput(fileList);},handlePreview(file) {this.dialogVisible = true;this.dialogImageUrl = file.url;},beforeUpload(file) {let _self = this;return new Promise((resolve, reject) => {policy().then(response => {console.log("这是什么${filename}");_self.dataObj.policy = response.data.policy;_self.dataObj.signature = response.data.signature;_self.dataObj.ossaccessKeyId = response.data.accessid;_self.dataObj.key = response.data.dir +getUUID()+"_${filename}";_self.dataObj.dir = response.data.dir;_self.dataObj.host = response.data.host;resolve(true);}).catch(err => {console.log("出错了...",err)reject(false);});});},handleUploadSuccess(res, file) {this.fileList.push({name: file.name,// url: this.dataObj.host + "/" + this.dataObj.dir + "/" + file.name; 替换${filename}为真正的文件名url: this.dataObj.host + "/" + this.dataObj.key.replace("${filename}",file.name)});this.emitInput(this.fileList);},handleExceed(files, fileList) {this.$message({message: "最多只能上传" + this.maxCount + "张图片",type: "warning",duration: 1000});}}
};
</script>
<style>
</style>

7.后端code实现

package com.qfedu.fmmall.controller;/****@author SmallMonkey*@Date 2023/2/10 13:07****/import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;@RestController
@CrossOrigin
@RequestMapping("/oss")
public class OssController {@RequestMapping("/policy")public Map<String,String> policy(){// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。String accessId = "LTAI5tRNby21a72dAhf4NbPa";String accessKey = "LTWOauYIuCkNF2O9zgU0Mm7HCuV5BE";// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "oss-cn-hangzhou.aliyuncs.com";// 填写Bucket名称,例如examplebucket。String bucket = "fmmallrebuild";// 填写Host地址,格式为https://bucketname.endpoint。String host = "https://" + bucket + "." + endpoint;// 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。// String callbackUrl = "https://192.168.0.0:8888";// 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。//可以加上当前的日期SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");String dir = simpleDateFormat.format(new Date()) + "/";//String objectName = dir + UUID.randomUUID().toString()+".png";// 创建ossClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);try {long expireTime = 30;long expireEndTime = System.currentTimeMillis() + expireTime * 1000;Date expiration = new Date(expireEndTime);PolicyConditions policyConds = new PolicyConditions();policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);byte[] binaryData = postPolicy.getBytes("utf-8");String encodedPolicy = BinaryUtil.toBase64String(binaryData);String postSignature = ossClient.calculatePostSignature(postPolicy);Map<String, String> respMap = new LinkedHashMap<String, String>();respMap.put("accessId", accessId);respMap.put("policy", encodedPolicy);respMap.put("signature", postSignature);respMap.put("dir", dir);respMap.put("host", host);respMap.put("expire", String.valueOf(expireEndTime / 1000));return respMap;
//服务进行上线之后,有一个外网可以访问的地址可以设置回调/*JSONObject jasonCallback = new JSONObject();jasonCallback.put("callbackUrl", callbackUrl);jasonCallback.put("callbackBody","filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());respMap.put("callback", base64CallbackBody);JSONObject ja1 = JSONObject.fromObject(respMap);*/} catch (Exception e) {// Assert.fail(e.getMessage());System.out.println(e.getMessage());}return null;}}

2.SpringCloud形式OSS上传

1.引入依赖

    <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alicloud-oss</artifactId><version>2.2.0.RELEASE</version></dependency>

2.后端实现code

@RestController
public class OssController {@AutowiredOSS ossClient;@Value ("${spring.cloud.alicloud.oss.endpoint}")String endpoint ;@Value("${spring.cloud.alicloud.oss.bucket}")String bucket ;@Value("${spring.cloud.alicloud.access-key}")String accessId ;@Value("${spring.cloud.alicloud.secret-key}")String accessKey ;@RequestMapping("/oss/policy")public Map<String, String> policy(){String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpointString format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());String dir = format; // 用户上传文件时指定的前缀。Map<String, String> respMap=null;try {long expireTime = 30;long expireEndTime = System.currentTimeMillis() + expireTime * 1000;Date expiration = new Date(expireEndTime);PolicyConditions policyConds = new PolicyConditions();policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);byte[] binaryData = postPolicy.getBytes("utf-8");String encodedPolicy = BinaryUtil.toBase64String(binaryData);String postSignature = ossClient.calculatePostSignature(postPolicy);respMap= new LinkedHashMap<String, String>();respMap.put("accessid", accessId);respMap.put("policy", encodedPolicy);respMap.put("signature", postSignature);respMap.put("dir", dir);respMap.put("host", host);respMap.put("expire", String.valueOf(expireEndTime / 1000));} catch (Exception e) {// Assert.fail(e.getMessage());System.out.println(e.getMessage());} finally {ossClient.shutdown();}return respMap;}
}

3.前端实现code

2. 商品管理系统OSS实现图片显示和图片上传

1.前端Code

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/semantic-ui@2.4.2/dist/semantic.min.css"><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script><!-- 引入样式 --><link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"><!-- 引入组件库 --><script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head><body><div class="fillcontain" id="app"><template><!-- <el-alerttitle="商品管理页面"type="success"show-icon></el-alert>--></template><h2 class="ui teal header" style="text-align: center;margin-top: 10px;">欢迎来到商品管理页面</h2><el-form :model="dataForm" class="search_container" label-width="100px" @keyup.enter.native="submit(1)"><el-row><el-col :span="8"><el-form-item label="农产品类别"><!-- <el-select filterable style="width: 220px;" v-model="dataForm.categoryName" default-first-optionfilterable allow-create clearable size="small" placeholder="选择商品一级分类"@change="changeSubCategory" ><el-option v-for="(item,index) in this.parentCategoryList" :key="index" :label="item.label":value="item.value" /></el-select> --><el-cascader filterable :show-all-levels="false" size="small" clearablev-model="dataForm.categoryIds" :options="options" :props="props" @change="handleChange"@getCheckedNodes="getCheckedNodes"><!-- 自定义显示的列 --><template slot-scope="{ node,data }"><span>{{data.categoryId}}、{{ data.categoryName}}</span></template></el-cascader></el-form-item></el-col><!-- <el-col :span="5"><el-form-item label="二级"><el-select style="width: 120px;" filterable allow-create @change="change" placeholder="二级分类"clearable size="small" v-model="dataForm.categoryName1"><el-option v-for="(item,index) in this.subOptions" :key="index" :label="item.label":value="item.value"></el-option></el-select></el-form-item></el-col> --><el-col :span="8"><el-form-item label="商品名称" label-width="120px"><el-input v-model="dataForm.product_name" placeholder="输入商品名称" clearable size="small"></el-input></el-form-item></el-col><el-col :span="8"><el-form-item label="商品的状态"><el-select v-model="dataForm.isup" clearable size="small"><el-option label="上架" value="1" style="color: teal;"> </el-option><el-option label="下架" value="0" style="color: red;"> </el-option></el-select><!-- <el-switch style="display: block"  v-model="dataForm.isup" active-value="1"inactive-value="0" active-color="#13ce66"inactive-color="#ff4949" active-text="上架" inactive-text="下架" @change="changeProductStatus(scope.row)"></el-switch>--></el-form-item></el-col><el-col :span="18"><el-form-item label="商品上架日期"><el-date-picker v-model="dataForm.submistrdte" type="date" placeholder="开始日期"value-format="yyyy-MM-dd" clearable size="small"></el-date-picker><span class="spanline">&nbsp;-&nbsp;</span><el-date-picker v-model="dataForm.submienddte" type="date" placeholder="结束日期"value-format="yyyy-MM-dd" @blur='dataBlur' clearable size="small"></el-date-picker></el-form-item></el-col><el-col :span="6" class="text_center"><el-button type="primary" icon="el-icon-search" @click="intDataList(1)" size="small"></el-button><el-button icon="el-icon-refresh" @click="resetForm" size="small"></el-button><el-button type="success" size="small" @click="addHandle">新增商品</el-button></el-col></el-row></el-form><!-- 查询结果列表 --><div class="listbox"><!-- 列表 --><el-table ref="multipleTable" :data="dataList" border :fit="true" style="width: 100%" disabled><el-table-column sortable type="index" label="序号" header-align="center" width="45"></el-table-column><el-table-column v-if="false" sortable prop="product_id" label="商品id" show-overflow-tooltipmin-width="100" disabled><template slot-scope="scope"><span> {{ scope.row.product_id || '--' }} </span></template></el-table-column><el-table-column sortable prop="product_name" label="商品名称" show-overflow-tooltip min-width="100"disabled><template slot-scope="scope"><span> {{ scope.row.product_name || '--' }} </span></template></el-table-column><el-table-column sortable prop="sell_price" label="商品销售价格" show-overflow-tooltip min-width="100"disabled><template slot-scope="scope"><span> {{ scope.row.sell_price || '--' }} </span></template></el-table-column><el-table-column sortable prop="sku_name" label="商品套餐名" show-overflow-tooltip min-width="80" disabled><template slot-scope="scope"><span> {{ scope.row.sku_name || '--' }} </span></template></el-table-column><el-table-column sortable prop="untitled" label="商品套餐" show-overflow-tooltip min-width="180" disabled><template slot-scope="scope"><span> {{ scope.row.untitled || '--' }} </span></template></el-table-column><el-table-column sortable prop="url" label="商品图片显示" show-overflow-tooltip min-width="100"disabled><template slot-scope="scope"><!-- 通过oss显示图片 --><img width="80px" height="25px" :src="scope.row.url" style="border-radius: 5px;"></template></el-table-column><el-table-column sortable prop="category_name" label="商品分类名称" show-overflow-tooltip min-width="100"><template slot-scope="scope"> {{ scope.row.category_name || '--' }} </template></el-table-column><el-table-column prop="isup" label="商品的状态" show-overflow-tooltip min-width="130" sortable><template slot-scope="scope"><!-- <span v-if="scope.row.isup==1" style="color:teal">上架</span><span v-if="scope.row.isup==0" style="color:red">下架</span> --><el-switch style="display: block" v-model="scope.row.isup" active-value="1" inactive-value="0"active-color="#13ce66" inactive-color="#ff4949" active-text="上架" inactive-text="下架"@change="changeProductStatus(scope.row)"></el-switch></template></el-table-column><el-table-column prop="sold_num" label="销售数量" show-overflow-tooltip min-width="100" sortable><template slot-scope="scope"> {{ scope.row.sold_num || '--' }} </template></el-table-column><el-table-column prop="content" label="商品说明" show-overflow-tooltip min-width="110" sortable><template slot-scope="scope"><span>{{ scope.row.content || '--' }}</span></template></el-table-column><el-table-column prop="create_time" label="商品创建时间" show-overflow-tooltip min-width="100" sortable><template slot-scope="scope"> {{ scope.row.create_time || '--' }} </template></el-table-column><el-table-column prop="update_time" label="商品更新时间" show-overflow-tooltip min-width="100" sortable><template slot-scope="scope"> {{ scope.row.update_time || '--' }} </template></el-table-column><el-table-column label="操作" show-overflow-tooltip min-width="180" fixed="right"><template slot-scope="scope"><el-button type="text" size="small" @click="copyHandle(scope.row)">复制</el-button><el-button type="text" size="small" @click="UpdateHandle(scope.row)">修改</el-button><!-- <el-buttontype="text"size="small"@click="saveHandle(scope.row, scope.$index, scope.row.id)"v-if="!scope.row.disabled">保存</el-button> --><el-button type="text" size="small" @click="deleteHandle(scope.row, scope.$index)">删除</el-button></template></el-table-column><el-button type="danger"> 新增</el-button></el-table><!-- 分页 --><el-row><el-col :span="24"><div class="pagination"><!-- 分页 --><el-pagination background @size-change="sizeChangeHandle" @current-change="currentChangeHandle":current-page="page.pageIndex" :page-sizes="[10, 20, 50, 100]":page-size="page.pageformSize" :total="page.totalPage"layout="total, sizes, prev, pager, next, jumper"></el-pagination></div></el-col></el-row></div><br><br><br><br><br><el-dialog title="商品信息修改" :visible.sync="dialogFormVisible"><el-form :model="form"><el-form-item label="商品名称" :label-width="formLabelWidth"><el-input v-model="form.product_name" autocomplete="off"></el-input></el-form-item><el-form-item label="商品价格" :label-width="formLabelWidth"><el-input v-model="form.sell_price" autocomplete="off"></el-input></el-form-item><el-form-item label="商品套餐名" :label-width="formLabelWidth"><el-input v-model="form.sku_name" autocomplete="off"></el-input></el-form-item><el-form-item label="商品套餐" :label-width="formLabelWidth"><el-input v-model="form.untitled" autocomplete="off"></el-input></el-form-item><el-form-item label="商品图片" :label-width="formLabelWidth"><!-- <el-upload ref="doctypeCrfile" class="upload-demo" drag :limit="3"action="http://localhost:8080/upload/uploadFile1" multiple :file-list="fileList":on-success="handleSucess" :show-file-list="true" v-model="form.pics" :auto-upload="false":before-upload="beforeAvatarUpload" list-type="picture"><i class="el-icon-upload"></i><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div><img v-if="imageUrl" :src="data:imageUrl" class="avatar" /></el-upload> --><el-uploaddraggable="true"class="upload-demo":action="obj.host":before-upload="ossPolicy":on-success="handleUploadSuccess"//上传时绑定的数据:data="obj":limit="1":file-list="fileList"list-type="picture"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="form.url" alt=""></el-dialog></el-form-item><el-form-item label="商品分类名称"><!-- <el-select filterable v-model="form.category_id" default-first-option filterable allow-createclearable size="small" placeholder="" @change="changeSubCategory" ><el-option v-for="(item,index) in this.parentCategoryList" :key="index" :label="item.label":value="item.value" /></el-select> --><el-cascader clearable v-model="form.categoryIds" :options="options" :props="props"@change="handleChange"><template slot-scope="{ node,data }"><span>{{data.categoryId}}、{{ data.categoryName}}</span></template></el-cascader></el-form-item></el-form-item><!--  --><el-form-item label="商品的状态" :label-width="formLabelWidth"><!-- <el-select v-model="form.isup" autocomplete="off"><el-option label="上架" value="1" style="color: teal;" checked></el-option><el-option label="下架" value="0" style="color: red;"></el-option></el-select> --><el-switch style="display: block" v-model="form.isup" active-value="1" inactive-value="0"active-color="#13ce66" inactive-color="#ff4949" active-text="上架" inactive-text="下架"></el-switch></el-form-item><el-form-item label="商品说明" :label-width="formLabelWidth"><el-input type="textarea" :rows="5" placeholder="请输入内容" v-model="form.content" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogFormVisible = false">取 消</el-button><el-button type="primary" @click="updateProduct(form)" :disabled="confirm">修 改</el-button></div></el-dialog><!-- 商品信息的保存 --><el-dialog title="商品添加" :visible.sync="dialogFormVisibleSave"><el-steps :space="800" :active="active" finish-status="success"><el-step title="步骤 1"></el-step><el-step title="步骤 2"></el-step></el-steps><el-form :label-position="labelPosition" :model="form" v-show="show"><h2>商品信息添加 </h2><el-form-item label="商品名称" :label-width="formLabelWidth"><el-input v-model="form.product_name" autocomplete="off"></el-input></el-form-item><el-form-item label="商品图片" :label-width="formLabelWidth"><!-- <el-upload ref="doctypeCrfile" class="upload-demo" drag :limit="3"action="http://localhost:8080/upload/uploadFile1" multiple :file-list="fileList":on-success="handleSucess" :show-file-list="true" v-model="form.url" :auto-upload="false"list-type="picture" :before-upload="beforeAvatarUpload"><i class="el-icon-upload"></i><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div><img v-if="imageUrl" :src="data:imageUrl" class="avatar" /></el-upload> --><el-uploaddraggable="true"class="upload-demo":action="obj.host":before-upload="ossPolicy":on-success="handleUploadSuccess"//上传时绑定的数据:data="obj":limit="2":file-list="fileList"list-type="picture"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="fileList[0].url" alt=""></el-dialog></el-form-item><el-form-item label="商品分类名称" :label-width="formLabelWidth"><!-- <el-cascader:props="defaultParams":options="this.parentCategoryList"v-model="subOptions1"@change="changeSubCategory"></el-cascader> --><!-- <el-select clearable v-model="form.category_id" placeholder="请选择活动区域"><el-option v-for="item in this.parentCategoryList" :key="item.value" :label="item.label":value="item.value"></el-option></el-select> --><el-cascader clearable v-model="form.categoryIds" :options="options" :props="props"@change="handleChange"></el-cascader></el-form-item><!--  --><el-form-item label="商品的状态" :label-width="formLabelWidth"><!-- <el-select v-model="form.isup" autocomplete="off"><el-option label="上架" value="1" style="color: teal;" checked></el-option><el-option label="下架" value="0" style="color: red;"></el-option></el-select> --><el-switch style="display: block" v-model="form.isup" active-value="1" inactive-value="0"active-color="#13ce66" inactive-color="#ff4949" active-text="上架" inactive-text="下架"></el-switch></el-form-item><el-form-item label="商品说明" :label-width="formLabelWidth"><el-input type="textarea" :rows="2" placeholder="请输入内容" v-model="form.content" autocomplete="off"@input="passInput"></el-input></el-form-item><p style="margin-left:66px;font-size:9px;text-align:center"> 还可以输入<strongstyle="color:red">{{numRemark}}</strong>个字 </p></el-form><el-form :label-position="labelPosition" :model="form" v-show="!show"><h2>商品属性信息添加 </h2><el-form-item label="商品套餐名称"><el-input v-model="form.sku_name" autocomplete="off"></el-input></el-form-item><el-form-item label="商品口味"><el-input v-model="form.untitled"></el-input></el-form-item><el-form-item label="商品原价"><el-input v-model="form.originPrice"></el-input></el-form-item><el-form-item label="商品售价"><el-input v-model="form.sellPrice"></el-input></el-form-item><el-form-item label="商品库存"><el-input type="number" v-model.number="form.stock"><template slot="append">件</template></el-input></el-form-item><el-row><el-col :span="18"></el-col><el-col :span="12"><el-form-item style="float: right;"><el-button @click="dialogFormVisibleSave = false">取 消</el-button><el-button type="primary" @click="saveProduct(form)">保存</el-button></el-form-item></el-col></el-row></el-form><div slot="footer" class="dialog-footer"><el-button style="margin-top: 12px;" @click="pre">上一步</el-button><el-button style="margin-top: 12px;" @click="next">下一步</el-button></div></el-dialog></div></div><script src="https://cdn.jsdelivr.net/npm/jquery@3.2/dist/jquery.min.js"> </script><script src="static/js/base.js"></script><script src="static/js/axios.min.js"></script><script src="static/js/cookie_utils.js"></script><script>var userId = getCookieValue("userId");var token = getCookieValue("token");new Vue({el: '#app',data: {labelPosition: 'right',active: 0,illcodeInputShow: true,show: true,numRemark: 400,url: "",formLabelWidth: '120px',dialogFormVisible: false,imageUrl: "",dialogFormVisibleSave: false,dataForm: {submienddte: "",submistrdte: "",isup: "",categoryIds: [],product_name: "",categoryName: "",categoryName1: "",},dataList: [{}, {}],//  图片的定义的数组fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}],obj:{OSSAccessKeyId:"",policy:"",signature:"",key:"",host:"",dir:"",},dialogVisible: false,// 分类数据categorydataList: [],options: [{value: 'zhinan',label: '指南',children: [{value: 'shejiyuanze',label: '设计原则',children: [{value: "",lable: ""}]}]}],parentCategoryList: [],subOptions1: [],subOptions: [],flag: false,props: {expandTrigger: 'hover',//multiple:true,          //这里设置为多选模式value: "categoryId",label: "categoryName",      //展示的lable名字children: "categories"    //展示子级},defaultParams: {value: 'value',label: 'label',children: this.subOptions},parenId: "",sbusiorgMap: [{sorgname: '1',}],category_id: 0,submistrdte: "",submienddte: "",disabled: true,page: {pageIndex: 1,pageSize: 10,totalPage: 0,},form: {pictureName: "",sell_price: "",url: "",//图片数组pics: [],categoryIds: [],//分类id},// 公共数据commonData: {},confirm: false,//  商品分类查询的idselectCategory_id1: 0,selectCategory_id2: 0,},methods: {handleChange(value) {console.log("", value);console.log("选中的值:", this.dataForm.categoryIds)},getCheckedNodes(leafOnly) {console.log("选中节点数组", leafOnly)},passInput(value) {// alert(value);console.log(value, "value");this.numRemark = 400 - value.length;if (this.numRemark < 0) {this.numRemark = 0;}if (value.length > 400) {this.form.content = this.form.content.substring(0, 400);this.$message({message: "输入的说明不可以大于400字",type: "error",showClose: true,});return;}},changeProductStatus(value) {console.log("最新商品信息", value);axios({url: baseUrl + "product/updateProductStatus",method: "post",data: value,}).then(res => {console.log("商品状态返回数据", res.data);if (res.data.code == 2) {ELEMENT.Message.success(res.data.msg);this.intDataList();}})},change(val) {console.log(val, "Category2")},next() {this.show = false;if (this.active++ > 2) this.active = 0;},pre() {this.show = true;if (this.active-- < 0) this.active = 0;},changeSubCategory(val) {// let label=this.$refs['cascaderAddr'].currentLabels;// console.log(label);this.dataForm.categoryName1 = null;axios({url: baseUrl + "index/subList",method: "post",headers: {token: token},data: val,}).then(res => {this.subOptions = res.data.data;console.log(this.subOptions);console.log(res.data, "parent")// ELEMENT.Message.success("更新商品信息成功");})},queryParenList() {axios({url: baseUrl + "index/parentlist",method: "post",headers: {token: token},data: userId,}).then(res => {this.parentCategoryList = res.data.data;console.log(res.data, "parent")// ELEMENT.Message.success("更新商品信息成功");})},saveProduct(val) {//    点击保存按钮---------- 图片的手动上传代码// var vm = this;// vm.$refs.doctypeCrfile.submit();console.log("商品地址---------",this.form.url);if (val.product_name == null || val.product_name.length == 0) {ELEMENT.Message.error("商品名称不可以为空");return;}if (val.categoryIds == null || val.categoryIds.length == 0) {ELEMENT.Message.error("商品分类名称必须选择");return;}if (val.originPrice.trim() == null) {ELEMENT.Message.error("商品原价不可以为空");return;}axios({url: baseUrl + "product/add",method: "post",data: val,}).then(res => {// console.log(res.data.msg);ELEMENT.Message.success(res.data.msg);this.intDataList();})},showCategorires() {console.log("3333333333333333333")var userId = getCookieValue("userId");var url2 = baseUrl + "index/categorylist";axios({method: "post",data: userId,url: url2,}).then(res => {console.log("商品分类数据111111111111:", res.data.data);this.categorydataList = res.data.data;this.options = this.getTreeData(res.data.data);this.options.children = res.data.data.categories;this.options.value = res.data.data.categoryId;this.options.label = res.data.data.categoryName;console.log(this.options, "----------CategoriesdataList")})},//递归判断列表,把最后的children设为undefinedgetTreeData(data) {for (var i = 0; i < data.length; i++) {if (data[i].categories.length < 1) {// children若为空数组,则将children设为undefineddata[i].categories = undefined;} else {// children若不为空数组,则继续 递归调用 本方法this.getTreeData(data[i].categories);}}return data;},// 商品保存updateProduct(row) {if (row.categoryIds == null || row.categoryIds.length == 0) {ELEMENT.Message.error("商品分类不可以为空");return;}axios({url: baseUrl + "product/update",method: "post",data: row,}).then(res => {ELEMENT.Message.success("更新商品信息成功");this.intDataList();})},// 删除deleteHandle(row, index) {let params = {product_id: row.product_id,sku_id: row.sku_id,};this.$confirm(`确定进行删除操作?`, "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {axios({url: baseUrl + "product/delete",method: 'post',data: params}).then((res) => {console.log(res.data);ELEMENT.Message.success(res.data.msg);this.intDataList();});});},// // 公共代码段-复制、修改// commenFn(row) {//   let copyObj = {//   product_name:row.product_name, //     category_name: row.category_name, //   content:row.content,//  isup:row.isup,//    soldNum:0,//   };//   this.commonData = copyObj;//   this.dataList.push(this.commonData);//   this.commonData = {};// },// 复制copyHandle(row) {// 功能代码//   this.commenFn(row);this.dialogFormVisibleSave = true;this.form = row;this.illcodeInputShow = false;ELEMENT.Message.success('复制成功');},addHandle(row) {// 功能代码//   this.commenFn(row);this.numRemark = 400;this.form = {};this.dialogFormVisibleSave = true;},// 修改功能UpdateHandle(row) {// 功能代码this.category_id = row.category_id;row.disabled = false;this.confirm = false;this.form = row;this.dialogFormVisible = true;},dataBlur() {if (this.dataForm.submistrdte > this.dataForm.submienddte) {this.dataForm.submienddte = "";ELEMENT.Message.error('开始日期不可以大于结束日期');}},// 每页数sizeChangeHandle(val) {this.page.pageSize = val;this.page.pageIndex = 1;this.intDataList(2);},// 当前页currentChangeHandle(val) {this.page.pageIndex = val;this.intDataList(2);},//  前往末页toLastPage() {let max = Math.ceil(this.tablePage.totalResult / this.tablePage.pageSize);this.handleCurrentChange(max);},// 重置resetForm() {this.dataForm.category_id = "",this.dataForm.product_name = "",this.dataForm.submistrdte = "",this.dataForm.submienddte = "",this.dataForm.categoryName = "",this.dataForm.categoryName1 = "",this.dataForm.categoryIds = [];this.dataForm.isup = "",this.intDataList(1);},// 支持enter键查询submit(val) {// console.log(this.dataForm.branchname );this.intDataList(val);},// 点击搜索按钮,请求数据intDataList(val) {// this.$store.dispatch("loading/CHANGE_LOADING", true);let userId = getCookieValue("userId");var params = {pageNum: this.page.pageIndex,pageSize: this.page.pageSize,categoryIds: this.dataForm.categoryIds,product_name: this.dataForm.product_name,createTime: this.dataForm.submistrdte,createTime1: this.dataForm.submienddte,isup: this.dataForm.isup,userId: userId}if (val === 1) {//起始日期为空,截止日期赋值起始日期if (this.submistrdte == '') {this.submistrdte = this.submienddte}//截止日期为空,起始日期赋值截止日期if (this.submienddte == '') {this.submienddte = this.submistrdte}// 666sessionStorage.setItem("datumTasks", JSON.stringify(params))}let token = getCookieValue("token");var url5 = baseUrl + "product/list";axios({url: url5,method: "post",headers: {token: token},data: params}).then(res => {this.dataList = [];console.log(res.data, "dataList-------------");this.dataList = res.data.list;// this.page.pageNum=1this.page.totalPage = res.data.total;this.pageIndex = res.data.pageNum;}).catch((err) => {});},//oss实现文件上传emitInput(val) {this.$emit('input', val)},handleRemove(file, fileList) {this.emitInput('');},ossPolicy(file){// 上传前,获取服务器给的签名axios({url:"http://localhost:8080/oss/policy",method:"get",}).then(res=>{console.log("come in ---------",res.data)this.obj.OSSAccessKeyId = res.data.accessId;this.obj.policy = res.data.policy;this.obj.dir = res.data.dir;this.obj.signature = res.data.signature; //传到oss的服务器地址this.obj.host = res.data.host;this.obj.key =res.data.dir + "${filename}";})},//文件上传成功时调用handleUploadSuccess(res, file) {console.log("上传成功...")this.showFileList = true;this.fileList.pop();this.fileList.push({name: file.name, url: this.obj.host + '/' + this.obj.key.replace("${filename}",file.name) });this.emitInput(this.fileList[0].url);console.log("图片上传oss后的地址",this.fileList[0].url);//赋值图片地址this.form.url = this.fileList[0].url;console.log(this.form.url);},},created() {this.intDataList();this.showCategorires();this.queryParenList();}})</script></body></html>

1.后端Code

package com.qfedu.fmmall.controller;/****@author SmallMonkey*@Date 2023/2/10 13:07****/import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;@RestController
@CrossOrigin
@RequestMapping("/oss")
public class OssController {@RequestMapping("/policy")public Map<String,String> policy(){// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。String accessId = "";String accessKey = "yourkey";// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "oss-cn-hangzhou.aliyuncs.com";// 填写Bucket名称,例如examplebucket。String bucket = "fmmallrebuild";// 填写Host地址,格式为https://bucketname.endpoint。String host = "https://" + bucket + "." + endpoint;// 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。// String callbackUrl = "https://192.168.0.0:8888";// 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。//可以加上当前的日期SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");String dir = simpleDateFormat.format(new Date()) + "/";//String objectName = dir + UUID.randomUUID().toString()+".png";// 创建ossClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);try {long expireTime = 30;long expireEndTime = System.currentTimeMillis() + expireTime * 1000;Date expiration = new Date(expireEndTime);PolicyConditions policyConds = new PolicyConditions();policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);byte[] binaryData = postPolicy.getBytes("utf-8");String encodedPolicy = BinaryUtil.toBase64String(binaryData);String postSignature = ossClient.calculatePostSignature(postPolicy);Map<String, String> respMap = new LinkedHashMap<String, String>();respMap.put("accessId", accessId);respMap.put("policy", encodedPolicy);respMap.put("signature", postSignature);respMap.put("dir", dir);respMap.put("host", host);respMap.put("expire", String.valueOf(expireEndTime / 1000));return respMap;
//服务进行上线之后,有一个外网可以访问的地址可以设置回调/*JSONObject jasonCallback = new JSONObject();jasonCallback.put("callbackUrl", callbackUrl);jasonCallback.put("callbackBody","filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());respMap.put("callback", base64CallbackBody);JSONObject ja1 = JSONObject.fromObject(respMap);*/} catch (Exception e) {// Assert.fail(e.getMessage());System.out.println(e.getMessage());}return null;}}

OSS(Object Storage Service)进行上传图片,下载图片(详细看文档可以完成操作)相关推荐

  1. JS使用技巧-如何解决谷歌浏览器下载图片、PDF文档时只打开不下载的问题?

    问题描述: 页面下载跨域的图片.pdf文件,浏览器总是自动打开,并且在下载列表里面不显示. 如何解决谷歌浏览器下载图片.PDF文档时只打开不下载的问题?如何变成直接下载? 解决方法: 使用js获取下载 ...

  2. 利用python3爬虫下载图片、pdf文档

    环境 语言环境:python3.6 操作系统:Win10 第三方库 requests 互联网上的资源大都是以二进制形式存储和运输的,如图片.pdf.音频.视频等,像.dat..ts等这些不常用的文件也 ...

  3. 阿里云对象存储OSS(Object Storage Service)

    文章目录 简介 endpoint:阿里云服务部署的地区位置 见解 开发步骤 配置文件 utils层(读取全局配置文件并赋值给类变量) service层 impl(基于oss驱动sdk实现类) cont ...

  4. 对象存储服务(Object Storage Service,OBS)

    对象存储服务(Object Storage Service,OBS) https://support.huaweicloud.com/obs/index.html 对象存储服务(Object Stor ...

  5. PNG图片转换word文档,不用下载软件,免费完成

    PNG格式也是我们工作中常见的图片格式,工作中难免会整理一些PNG图片资料,大家都是怎么做的呢?小编给大家分享一个方法,就是把PNG图片转换word文档,这样就方便我们去整理了,并且无需下载软件就可以 ...

  6. Python实现某du内容下载, 保存到word文档

    前言 今天来点不一样的 用Python实现某du文库vip内容下载, 保存到word文档 前期准备 环境使用 python 3.8 pycharm 模块使用 requests >>> ...

  7. 网站不让复制文字??教你破解复制+白嫖下载百度等各种文档

    前阵子需要写篇 xxxx 感想的文章,当然,这种一般都是学校要求写的,作为高中作文在及格边缘徘徊的"好学生",写是不可能写的了,只能拿出我的 从 CV 大法,去各大网站搜索白嫖别人 ...

  8. 30个值得收藏可免费搜索/下载PDF电子图书(文档)的搜索引擎

    « SooPAT专利搜索引擎为学知识搜索 » 30个值得收藏可免费搜索/下载PDF电子图书(文档)的搜索引擎 实用酷站 | 评论(0) | 348 views | 一 26th, 2011 PDF全称 ...

  9. Word电子扫描仪 word文档转换为图片Pdf,Word文档扫描成Pdf,word文档加密 word转图片 word转pdf

    Word文档转换为图片Pdf,Word文档扫描成Pdf Word转换为图片Pdf 1.        Word转换为Pdf,程序很多,但转换后的Pdf,还可以复制,虽可以加密禁止复制,但市场上太多的P ...

最新文章

  1. 机器学习之条件随机场CRF一点理解
  2. 美国计划让“人工智能”去搜寻外星人!
  3. Knockout2.x:ko.dataFor()、ko.contextFor()使用
  4. Individual Project-——word_frequency——final requirement
  5. 【代码笔记】Web-JavaScript-JavaScript调试
  6. rust军用船指令_Rust基础学习笔记(五):Cargo与Crates.io
  7. deepin卸载了python_Deepin-Linux下python卸载与安装(失败的折腾)
  8. remote: GitLab: Author ‘xxx‘ is not a member of team(Git修改和配置本地用户名和邮箱)
  9. ora-28547 可能是oracle net 管理错误_PostgreSQL与Oracle:成本、易用性和功能上的差异...
  10. 快逸报表研究-冻结表头
  11. linux的软件源修改
  12. 哈工大车万翔教授:NLPer的核心竞争力是什么?
  13. Django——jinja2配置与使用
  14. yolov3-tiny原始weights模型转onnx模型并进行推理
  15. RFC2616中文版
  16. Github十大深度学习项目
  17. Linux C编程下没有 itoa()函数的问题
  18. vanilla是什么意思
  19. 为什么ZMap用一个小时内就能扫遍整个互联网
  20. 木马程序,原来还有发展,现在居然还有好多代?

热门文章

  1. 《传习录》知行合一的译文
  2. fb50 sap 报记账码未定义_【FICO系列】SAP 关于SAP中的记账码的解释
  3. 细胞治疗car-t行业最新进展(2021年9月)
  4. picsart下载_PicsArt美易照片编辑下载
  5. setup小工具安装
  6. 【IVI】1. Android Automotive OS 安卓车载操作系统白皮书
  7. Android内存优化的知识梳理
  8. 视通助力中国航天某院多媒体会议室建设
  9. 卡迪夫大数据专业排名_2019英国大数据解析
  10. elsevier投稿的一些事情