表单:
<div class="form-group">
<label class="col-sm-2 control-label">图片</label>
<div class="col-sm-8 media-picker">
<div class="input-group">
<a href="javascript:void(0)" class="button media-picker-button" data-id="images" id="images_uploader" data-multiple="multiple" style="z-index: 98;">
<span>+</span>
<input type="hidden" id="images" name="images" value="" data-oss-path="courses">
</a>
</div>
<p class="help-block">多图上传,最多上传8张</p>
</div>
</div>
到阿里云下载需要的实例文件,我是用的服务端签名zh直传
https://help.aliyun.com/document_detail/31926.html?spm=a2c4g.11186623.6.637.rwzYfK
把前端文件拷贝下,如我把plupload拷贝到了public/plugins/下,把其他upload.js和.upload.js.swpkao拷贝到了public/aliyunoss下
在laravel的app下新建libs文件夹,并在composer.json中配置autoload
"classmap": [
"database/seeds",
"database/factories",
"app/Libs"
],
在libs下新建Aliyunoss.php
把下载下来的实例php整理下
namespace App\Libs;
class Aliyunoss {
private $id;
private $key;
private $host;
public function __construct()
{
$this->id= 'id';
$this->key= 'key';
$this->host = 'ossurl';
}
public function get_access_info($dir = 'images')
{
$now = time();
$expire = 30; //设置该policy超时时间是10s. 即这个policy过了这个有效时间,将不能访问
$end = $now + $expire;
$expiration = $this->gmt_iso8601($end);
$dir = $dir . '/';
//最大文件大小.用户可以自己设置
$condition = array(0=>'content-length-range', 1=>0, 2=>1048576000);
$conditions[] = $condition;
$key = $this->key;
//表示用户上传的数据,必须是以$dir开始, 不然上传会失败,这一步不是必须项,只是为了安全起见,防止用户通过policy上传到别人的目录
$start = array(0=>'starts-with', 1 => '$key', 2 => $dir);
$conditions[] = $start;
$arr = array('expiration'=>$expiration,'conditions'=>$conditions);
//echo json_encode($arr);
//return;
$policy = json_encode($arr);
$base64_policy = base64_encode($policy);
$string_to_sign = $base64_policy;
$signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->key, true));
$response = array();
$response['accessid'] = $this->id;
$response['host'] = $this->host;
$response['policy'] = $base64_policy;
$response['signature'] = $signature;
$response['expire'] = $end;
//这个参数是设置用户上传指定的前缀
$response['dir'] = $dir;
return json_encode($response);
}
private 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";
}
}
在后台新建UploadController.php,并建立路由
namespace App\Http\Controllers\Backend;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Libs\Uploads;
use App\Libs\Aliyunoss;
class UploadsController extends Controller {
public function aliyun_access($ossdir = 'images') {
$aliyunoss = new Aliyunoss();
return $aliyunoss->get_access_info($ossdir);
}
}
修改前端upload.js文件
如果只是单传,直接就可以使用,但实际开发中一个页面可能会用到很多shan上传,所以需要整理下js文件,我参考了网上一些资料
accessid = ''
accesskey = ''
host = ''
policyBase64 = ''
signature = ''
callbackbody = ''
filename = ''
key = ''
expire = 0
g_object_name = ''
g_object_names = new Array() //多图片上传保持
g_object_name_type = 'random_name'
now = timestamp = Date.parse(new Date()) / 1000;
currentUrl = window.location.href;
backendIndex = currentUrl.indexOf('backend');
baseBackend = currentUrl.substr(0, backendIndex);
function send_request(dir)
{
var xmlhttp = null;
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
if (xmlhttp!=null)
{
serverUrl = baseBackend + 'backend/getoss/' + dir
xmlhttp.open( "GET", serverUrl, false );
xmlhttp.send( null );
return xmlhttp.responseText
}
else
{
alert("Your browser does not support XMLHTTP.");
}
};
function get_signature(dir)
{
//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一下.3s 做为缓冲
now = timestamp = Date.parse(new Date()) / 1000;
if (expire < now + 3)
{
body = send_request(dir)
var obj = eval ("(" + body + ")")
host = obj['host']
policyBase64 = obj['policy']
accessid = obj['accessid']
signature = obj['signature']
expire = parseInt(obj['expire'])
callbackbody = obj['callback']
key = obj['dir']
return true;
}
return false;
};
function random_string(len) {
len = len || 32;
var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
var maxPos = chars.length;
var pwd = '';
for (i = 0; i < len; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
}
function get_suffix(filename) {
pos = filename.lastIndexOf('.')
suffix = ''
if (pos != -1) {
suffix = filename.substring(pos)
}
return suffix;
}
function calculate_object_name(filename)
{
suffix = get_suffix(filename)
g_object_name = key + random_string(20) + suffix
return ''
}
function set_upload_param(up, filename, ret, dir)
{
if (ret == false)
{
ret = get_signature(dir)
}
g_object_name = key;
if (filename != '') {
suffix = get_suffix(filename)
calculate_object_name(filename)
}
new_multipart_params = {
'key' : g_object_name,
'policy': policyBase64,
'OSSAccessKeyId': accessid,
'success_action_status' : '200', //让服务端返回200,不然,默认会返回204
'callback' : callbackbody,
'signature': signature,
};
up.setOption({
'url': host,
'multipart_params': new_multipart_params
});
up.start();
}
$(document).ready(function() {
//上传
$('.media-picker').each(function() {
var el = $(this);
var elbtn = el.find('.media-picker-button');
var multi_selection = false;
// 是否多文件上传
if(elbtn.attr('data-multiple') == 'multiple') {
multi_selection = true;
}
// 上传目录
var inputField = el.find('input[type=hidden]');
var ossdir = inputField.attr('data-oss-path');
var uploader = new plupload.Uploader({
runtimes : 'html5,flash,silverlight,html4',
browse_button : elbtn.attr('data-id') + '_uploader',
multi_selection: multi_selection,
auto_start: true,
flash_swf_url : '../plupload/js/Moxie.swf',
silverlight_xap_url : '../plupload/js/Moxie.xap',
url : 'http://oss.aliyuncs.com',
filters: {
mime_types : [ //只允许上传图片和zip,rar文件
{ title : "Image files", extensions : "jpg,gif,png,bmp" },
{ title : "Video files", extensions : "mp4,3gp" }
],
max_file_size : '10mb', //最大只能上传10mb的文件
prevent_duplicates : false //不允许选取重复文件
},
init: {
PostInit: function() {
set_upload_param(uploader, '', false, ossdir);
return false;
},
BeforeUpload: function(up, file) {
set_upload_param(up, file.name, true, ossdir);
},
FilesAdded: function(up) {
up.start(); //选择完后直接上传
},
FileUploaded: function(up, file, info) {
if (info.status == 200)
{
var file_type = file.type;
var is_image = file_type.indexOf('image');
var is_video = file_type.indexOf('video');
if (multi_selection) {
// 多文件转为json
g_object_names.push(g_object_name);
inputField.val(JSON.stringify(g_object_names));
// 把图片显示出来
var imageHtml = '';
for(var i = 0; i < g_object_names.length; i++) {
if(is_image > -1) {
imageHtml += '<li><div class="img-info"><img src="'+ host + '/' + g_object_names[i] +'"/><p>'+ g_object_names[i] +'</p><div class="delete-image"> X </div></div></li>';
}
if(is_video > -1) {
imageHtml += '<li><div class="img-info"><video controls src="'+ host + '/' + g_object_names[i] +'"></video><p>'+ g_object_names[i] +'</p><div class="delete-image"> X </div></div></li>';
}
}
el.find('.medias-list ul').html(imageHtml);
} else {
// 单文件直接用名称,
inputField.val(g_object_name);
// 把图片显示出来
var imageHtml = '';
if(is_image > -1) {
imageHtml = '<li><div class="img-info"><img src="'+ host + '/' + g_object_name +'"/><p>'+ g_object_name +'</p><div class="delete-image"> X </div></div></li>';
}
if(is_video > -1) {
imageHtml = '<li><div class="img-info"><video src="'+ host + '/' + g_object_name +'"></video><p>'+ g_object_name +'</p><div class="delete-image"> X </div></div></li>';
}
el.find('.medias-list ul').html(imageHtml);
}
}
else
{
alter(info.response);
}
},
Error: function(up, err) {
if (err.code == -600) {
alter("\n选择的文件太大了,可以根据应用情况,在upload.js 设置一下上传的最大大小");
}
else if (err.code == -601) {
alter("\n选择的文件后缀不对,可以根据应用情况,在upload.js进行设置可允许的上传文件类型");
}
else if (err.code == -602) {
alter("\n这个文件已经上传过一遍了");
}
else
{
alter("\nError xml:" + err.response);
}
}
}
})
uploader.init();
})
// 删除
$('.media-picker').each(function() {
var el = $(this)
var inputField = el.find('input[type=hidden]');
var fileName = inputField.val();
var elbtn = el.find('.media-picker-button');
var multi_selection = false;
// 是否多文件上传
if(elbtn.attr('data-multiple') == 'multiple') {
multi_selection = true;
}
if(multi_selection) {
el.on('click', '.delete-image', function() {
var elDel = $(this);
// 得到filename
var currentFileName = elDel.prev('p').html();
// 删除当前的父级li
elDel.parent().parent().remove();
// 重新赋值数组
var fileNames = new Array();
if(g_object_names != '') {
fileNames = g_object_names;
} else {
fileNames = $.parseJSON(fileName);
}
// 去掉数组中的当前值
fileNames.pop(currentFileName);
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
});
$.ajax({
type: "POST",
url: baseBackend + "backend/deleteoss",
data: "filename=" + currentFileName,
success: function(msg){
console.log(msg)
}
});
inputField.val( JSON.stringify(fileNames));
})
} else {
el.on('click', '.delete-image', function() {
// 显示值为空
el.find('.medias-list ul').html('');
inputField.val('');
// oss删除
if(g_object_name != '') {
fileName = g_object_name;
}
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
});
$.ajax({
type: "POST",
url: baseBackend + "backend/deleteoss",
data: "filename=" + fileName,
success: function(msg){
console.log(msg)
}
});
})
}
})
})