PHP试题网_中国最大的免费网络PHP试题测试平台,PHP试卷调查,PHP试卷模板、PHP考试测验
公告: PHP试题网于2022.06.21变更为少儿编程学院

单纯的javascript/js上传文件到oss会直接泄漏相应的key/secret等重要信息,所以上传时要先请求下PHP,然后拿着对应的信息就可以直接上传到OSS了。


第1步:上传表单:

<tr><td style="text-align:right;">上传mp3封面:</td><td style="text-align:left;">

				<span class="imgs"></span>
				<span class="imgs_file_btn">
        		<input type="file" name="file_conver" class="myfile layui-btn layui-btn-primary" value="" >
				</span>

        	</td></tr>


第2步:

引入我们写好的js文件: 

<script src="{$Think.BASE_SITE_ROOT}/static/oss_jq.js?time=1557452966" charset="utf-8"></script>

oss_jq.js内容如下:

;(function ($) {
    $.fn.extend({
        uploadUtil: function uploadUtil(options) {
            var that = this;
            $(this).on('change', function (e) {
                var file = e.target.files[0];
                var tokenUrl = options.tokenUrl;
                var filePrefix = options.filePrefix;
                var match = options.match;
                var callback = options.callback;
                var bucket = options.bucket;
                if (!bucket) {
                    bucket = 'mymall';//桶
                }
                // 只选择图片文件
                if (match) {
                    if (!file.type.match(match)) {
                        return false;
                    }
                }
                $.get(tokenUrl, { prefix: filePrefix, bucket: bucket }, function (res) {
                    var ossData = new FormData();
                    var realFilename = file.type.split('/');
                    ossData.append('OSSAccessKeyId', res.accessid);
                    ossData.append('policy', res.policy);
                    ossData.append('Signature', res.signature);
                    ossData.append('key', res.dir);
                    ossData.append('success_action_status', 201); // 指定返回的状态码
                    ossData.append('file', file, filePrefix + res.timestamp + '.' + realFilename[1]);
                    $.ajax({
                        url: res.host,
                        data: ossData,
                        dataType: 'xml',
                        processData: false,
                        contentType: false,
                        type: 'POST',
                        context: that
                    }).done(function (data) {
                        // 返回的上传信息
                        if ($(data).find('PostResponse')) {
                            var resq = $(data).find('PostResponse');
                            var nameKey = $(e.target).attr('id');
                            that[0].value = '';
                            $('img[name="' + nameKey + '"]').attr('src', resq.find('Location').text()).show();
                            $('input[name="' + nameKey + '"]').val(resq.find('Key').text());
                            if (callback) {
                                callback.apply(this, [res.host, resq.find('Key').text()]);
                            }
                        }
                    });
                }, 'json');
            });
        }
    });
})(jQuery);


第3步:调用上面的JS写好的方法:

//图片上传
	$('input[name="file_conver"]').uploadUtil({
		tokenUrl: '/api/oss_token/getToken',//获取oss信息
		filePrefix: 'music/{$day}/',//目录前缀,可以自定义
		match: 'image.*',//上传要匹配的文件类型
		callback: function (imgHost, imgStr) {
			let arr = imgStr.split('/');
			let html = '<img src="' + imgHost + imgStr + '">' +
				'<input type="hidden" name="image" value="' + imgHost + imgStr + '">';//将上传后的图片显示出来并将值放到隐藏域
			$('.imgs').html(html);
			$('.imgs_file_btn').hide();
		}
	});


第4步:/api/oss_token/getToken取出key/secret代码:

<?php

namespace app\api\controller;


use think\Controller;

class OssToken extends Controller
{
    public function getToken()
    {
        $bucket = request()->get('bucket');
        $bucket = empty($bucket) ? 'mymall' : $bucket;
        //自行设置AccessKey和相应Bucket的外网域名

        $id = 'OSS后台的id';
        $key = 'OSS后台的key';
        // h5下去除协议名称,由前端自行决定采用协议的类型
        $host = '//'.$bucket.'.阿里云OSS给我们的域名/';

        $prefix = request()->get('prefix');
        $prefixs = explode('/', $prefix);
        array_pop($prefixs);

        $now = time();
        $expire = 10; //设置该policy超时时间是10s. 即这个policy过了这个有效时间,将不能访问
        $end = $now + $expire;
        $expiration = $this->gmt_iso8601($end);

        //文件大小范围.用户可以自己设置
        $condition = array('content-length-range', 0, 1048576000);

        //设置用户上传指定的前缀
        $dir = 'home/' . implode('/', $prefixs) . '/';
        //用户上传数据的位置匹配,这一步不是必须项,只是为了安全起见,防止用户通过policy上传到别人的目录
        $start = array('starts-with', '$key', $dir);

        //设置bucket
        $bucket = array('eq', '$bucket', $bucket);

        $conditions = array($bucket, $condition, $start);


        $arr = array('expiration'=>$expiration,'conditions'=>$conditions);
        //echo json_encode($arr);
        //return;
        $policy = json_encode($arr);
        $base64_policy = base64_encode($policy);
        $signature = base64_encode(hash_hmac('sha1', $base64_policy, $key, true));

        $response = array(
            'accessid' => $id,
            'host' => $host,
            'policy' => $base64_policy,
            'signature' => $signature,
            'expire' => $end,
            'timestamp' => date('YmdHis') . mt_rand(10000, 99999),
            'dir' => $dir.'${filename}'
        );
        header('Content-Type: application/json;charset=utf-8');
        echo json_encode($response);
        exit;
    }

    function gmt_iso8601($time) {
        $dtStr = date("c", $time);
        $mydatetime = new \DateTime($dtStr);
        $expiration = $mydatetime->format(\DateTime::ISO8601);
        $pos = strpos($expiration, '+');
        $expiration = substr($expiration, 0, $pos);
        return $expiration."Z";
    }
}



第5步:大功告成。注意:由于是在H5/pc上的代码,返回的文件地址是//开头的协议文件地址,传到PHP后台时,要处理下。不然APP无法识别。


作者:OK兄 浏览次数:78