laravel 圖片上傳阿里雲oss
阿新 • • 發佈:2019-01-10
表單:
<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直傳
把前端檔案拷貝下,如我把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 oldFiles = inputField.val();
if(oldFiles != '') {
var oldFilesArr = $.parseJSON(oldFiles);
for(var x = 0; x < oldFilesArr.length; x++) {
g_object_names.push(oldFilesArr[x]);
}
}
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,jpeg,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 controls 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)
}
});
})
}
})
})