JAVA实现服务端获取签名后前端直传文件到oss服务器:前端到后端

项目场景:

对于文件上传大家都不陌生,基本上都是上传到自己的服务器后再通过服务器上传到阿里oss服务器上,我现在做的项目是需要上传视频的,这个功能其实已经做好了,但是由于视频文件比较大上传到服务器再上传oss的耗时比较长,就要换一种方式从前端直接上传到oss服务器上

介绍:

传统方式:
Web端常见的上传方法是用户在浏览器或app端上传文件到应用服务器,然后应用服务器再把文件上传到OSS,如下图所示:JAVA实现服务端获取签名后前端直传文件到oss服务器:前端到后端_第1张图片
上传慢:用户数据需先上传到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
扩展性差:如果后续用户多了,应用服务器会成为瓶颈。
费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,那么将能省下几台应用服务器。

直传的方式:
1.直接通过js直传的.但是appid与appkey都暴露在了前端.这样很不安全,最好不要采用,不过可以试着玩玩。
JavaScript客户端签名直传
2.前端向后台请求只去请求获取签名的接口,然后在拿到签名认证后直接向oss服务上传文件,我就是采用的这种方式,因为我并没有用到回调函数,所以就采用这种方式,流程图如下:
服务端请求签名后直传
JAVA实现服务端获取签名后前端直传文件到oss服务器:前端到后端_第2张图片
3.采用服务端签名后直传方案有个问题:大多数情况下,用户上传数据后,应用服务器需要知道用户上传了哪些文件以及文件名;如果上传了图片,还需要知道图片的大小等,为此OSS提供了上传回调方案。流程图如下:服务端签名直传并设置上传回调
JAVA实现服务端获取签名后前端直传文件到oss服务器:前端到后端_第3张图片

进入正题:

先来看看前端的代码
我这个项目中用到的layui的,我在他的第三方插件中找到了一个大哥写的组件,并用这个组件实现了我所需的功能,这边附上大哥的博客地址以及我已经下载好了的插件压缩包**插件源码的下载的地址,方便大家使用。
其实这个插件的详细参数说明在文件里都有,因为我也是第一次弄oss直传,弄得详细一点让第一次做这个功能爪哇小伙伴少花费一点时间,我还是贴出来方便大家查看,以下是文件上传js的调用:

 aliossUploader.render({
                elm:'#uploadBatchFileOther', //上传文件绑定的id
                fileType:'video',  //文件类型
                multiple:false,  //是否多文件上传 否
                layerArea:['800px','500px'],
                layerTitle:'上传文件到阿里云OSS',
                policyUrl:ctx+"courseMediaInfo/getOSS", //后台请求签名的路径,换成你们的就行
                policyData:{},//请求签名的参数,没有可不写
                policyHeader:{
                    Authorization:layui.data('xxx-data').Authorization //请求签名的headers
                },
                codeFiled:'code',//请求签名后返回的状态字段
                codeStatus:0,//请求签名后返回的状态码值
                policyMethod:'GET',//请求签名的方法类型
                accessidFiled : 'accessid',//阿里的accessKeyId
                policyFiled : 'policy',//签名返回的策略policy(也叫表单域)
                signatureFiled : 'signature',//返回的签名(主要就是这个签名)
                httpStr:'https',//上传至oss时是否https
                region:'oss-cn-hangzhou',//oss的数据中心所在的区域(在你的yml配置文件中可以找到)
                bucket: 'xxx-data',//oss的存储空间的名称(你要上传到哪个文件就是哪个名称)
                prefixPath:'course/',//上传时的前缀(相当于在你的oss存储空间多一级目录,要提前在你的oss存储空间新建好,要不然上传的时候会报错找不到文件夹)
                allUploaded:function(res){//成功回调
                    // var s = JSON.stringify(res);
                    // layer.msg(JSON.stringify(res));
                    // console.log(s[3]);
                     $view.find("#courseUrl").val(res[0].ossUrl);
                   /* var var1 = JSON.parse(res).var;*/

                },
                policyFailed:function(res){//失败回调
                    layer.msg(JSON.stringify(res));
                },
                uploadRenderData:{//设置文件大小,还有其他的参数可自行设置(下载源码或者去大哥的博客下看)
                    size:200000 //单位kb
                }
            });

提示: 这个地方是上传文件调用所需的,真证用到的源码js在下载插件后的一个叫aliossUploader.js的文件里,可以下载后根据自己的需求自行修改,因为我是采用的这个插件,所以我后台验证签名后返回的格式都是按照所需的参数进行封装的。
需要注意一下的是请求签名返回的参数结构,其实你要关注一下什么是policy以及他的语法,如何生成signature,这样你才能写后台的接口

{
	"code": 0,
	"success": true,
	"msg": "签名成功",
	"data": {
		"accessid": "XXXXX",
		"host": "http://XXXXX.oss-cn-shanghai.aliyuncs.com",
		"policy": "XXXX==",
		"signature": "XXXX=",
		"expire": 1554851252
	}
}

在这里附上链接,因为阿里的文档实在是太分散了,我自己找的时候都找了半天
你写这个小功能就必须了解:
PostObject使用HTML表单上传Object到指定Bucket
Policy 语法结构
以及阿里提供的接口demo我已经下载好了你可以自己去找或者用我的下载好了的都行


(**再来看看后端的接口**)
public class CourseMediaInfoController extends BaseController {

    private final ICourseMediaInfoService courseMediaInfoService;
    @Value("${aliyun.oss.endpoint}")
    private String endpoint; //这个值你的配置文件中有其实就是 http://oss-cn-hangzhou.aliyuncs.com
    @Value("${aliyun.oss.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.oss.accessKeySecret}")
    private String accessKeySecret;
    @Value("${aliyun.oss.bucketName.qyjz}")
    private String bucketName; //oss存储空间名称

    //oss存储课时文件前缀
    private String dir = "course/";
    
    @GetMapping("courseMediaInfo/getOSS")
    @ResponseBody
    //@RequiresPermissions("courseMediaInfo:list")
    public Map<String, Object> getOSS() {
        HashMap<String, Object> map1 = new HashMap<>();
        try{
            //开启oss客户端
            OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime *1000;
            Date expiration = new Date(expireEndTime);


            //生成的到期时间转换位s,并转换为String
            String expire = String.valueOf(expireEndTime / 1000);
            PolicyConditions policyConditions = new PolicyConditions();

            //构造用户表单域Policy条件
            PolicyConditions policyConds = new PolicyConditions();
            //设置上传文件大小的范围
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            //设置上传的路径的前缀:就是上传到指定文件夹
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            //根据到期时间生成policy策略
            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            //对policy进行UTF-8编码后转base64
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String endPolicy = BinaryUtil.toBase64String(binaryData);
            //生成签名,policy表单域作为填入的值,将该值作为将要签名的字符串。
            String signature = ossClient.calculatePostSignature(postPolicy);

            //封装参数参数返回
            HashMap<String, Object> map = new HashMap<>();
            map.put("accessid",accessKeyId);
            map.put("host",endpoint);//这里我是直接传过去的,因为在前端访问oss的时候做了拼接的,可以在aliossUploader.js里面找到
            map.put("policy",endPolicy);
            map.put("signature",signature);
            map.put("expire",expire );
            map1.put("code",0);
            map1.put("success",true);
            map1.put("msg","签名成功");
            map1.put("data",map);
        }catch (Exception e){
            e.printStackTrace();
        }
        return map1;
    }
    }

这就是后台接口的代码,其实和阿里的demo一摸一样,只是我做了根据插件做了一下修改,添加了注释,因为不加说明我第一眼看上去都不知道这些步骤是干啥的,注意一点的是你的文件上传的前缀要和js那写一致,要不然会报错说你文件夹不存在


注意事项:

1.一定要在阿里的控制台设置post请求跨域,别问我怎么知道的,看下图:JAVA实现服务端获取签名后前端直传文件到oss服务器:前端到后端_第4张图片
2.注意下前端传过在文件上传时的信息,如果上传除了出了问题可以看下请求体的信息,这就是我前面说到的找不到文件夹的错误,如下图:
JAVA实现服务端获取签名后前端直传文件到oss服务器:前端到后端_第5张图片
JAVA实现服务端获取签名后前端直传文件到oss服务器:前端到后端_第6张图片
更多的错误码阿里有提供的错误码也可以自行百度

ps:我只是给我做过的事情记录一下,希望对大家有帮助,如果记得要把前端的插件和阿里demo下载下来对比着看这样上手快一些,不会耽误时间最少有方向,还要记得在你的pom,xml将oss的依赖引入 (下载资源我已经设置0积分但csdn会自动加积分,如果需要得可以留言说 我把重新积分改为0)

你可能感兴趣的:(oss,java,javascript)