У меня есть мобильный сайт m.example.com - с телефона я хочу, чтобы посетители выбирали файл с Google Диска и отправляли его на сервер, на котором размещен файл m.example.com. По сути, эмуляция простой загрузки <input type="file">
как на рабочем столе.
Насколько я понимаю, рабочий процесс выглядит следующим образом:
1) Пользователь выбирает файл с помощью Picker, который отправляет метаданные выбранного файла на мой веб-клиент (т.е. HTML/Javascript, работающий на телефоне/планшете)
2) Я отправляю это на свой сервер через ajax или просто скрытое поле формы
3) мой сервер отправляет запрос в API Google для получения файла, а затем сохраняет его в файловой системе сервера
Поэтому мне нужна помощь:
а) правильные ли эти шаги, и есть ли другой способ сделать это, или даже услугу, которую я могу использовать, что позволит моим пользователям сайта выбирать свои файлы у одного из нескольких провайдеров облачных хранилищ?
а) если мои шаги верны, и это единственный способ, я застрял на 3) частичном сервере, который говорит с API.
До сих пор я закрыл сборщик, как здесь, - всплывающее окно Google picker auth блокируется и получает URL-адрес файла. Я еще не сделал 2), я просто вручную помещаю URL-адрес файла в мой скрипт downlaod.
Я использую PHP, и файл, который я хочу, чтобы downlaod на мой сервер мог быть общедоступным или частным, зависит от конечного пользователя.
Я потерялся в документах API (как в man-страницах, а не в документе google), и я смущен https://developers.google.com/api-client-library/php/start/get_started (вызовите эти документы API) и https://developers.google.com/drive/web/quickstart/quickstart-php (вызов этого документа на Диске) - эти два разных API?
Я следил за ссылками из документов API и устанавливал здесь клиента: https://github.com/google/google-api-php-client, но при попытке "Шаг 3: Настроить образец" в Документах на Диске я получить много ошибок, таких как файлы, которые не были найдены, класс not fount и т.д., так что это заставляет меня думать, что therr - это два разных API/Клиента, задокументированных здесь, - может кто-то, пожалуйста, указать мне в правильном направлении, чтобы начать?
ОБНОВИТЬ
Я установил клиент PHP в github, связанный с этим https://developers.google.com/api-client-library/php/start/get_started.
Это выглядит так:
Я запустил файл simplefileupload.php в каталоге примеров - работал в первый раз, мне нужно было только указать подробности моего проекта
Итак, перейдите на страницу https://developers.google.com/drive/web/quickstart/quickstart-php#step_3_set_up_the_sample и создал файл drive_rest_api_step_3.php в корневом каталоге google-api (как показано на экране захвата)
Got Fatal error: require_once(): Failed opening required 'src/Google_Client.php' (include_path='.: /usr/local/lib/php') in/path/to/google-api/drive_rest_api_step_3.php on line 5
В библиотеке нет Google_Client.php, но есть src/Google/Client.php, поэтому я редактирую require_once, чтобы использовать это.
Теперь получите Failed opening required 'src/contrib/Google_DriveService.php'
- снова поиск этого файла не дает результатов, но есть src/Google/Service/Drive.php, поэтому используйте пример редактирования:
Требуется (на https://developers.google.com/drive/web/quickstart/quickstart-php#step_3_set_up_the_sample):
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_DriveService.php';
Теперь:
require_once 'src/Google/Client.php';
require_once 'src/Google/Service/Drive.php';
Теперь получение Fatal error: Class 'Google_Service' not found in/path/to/google-api/src/Google/Service/Drive.php on line 32
Поэтому я думаю, что есть проблемы с двумя наборами руководств, либо они используют разные библиотеки, либо https://developers.google.com/drive/web/quickstart/quickstart-php#step_3_set_up_the_sample устарели, хотя сказано Последнее обновление 30 марта 2015 года.
Вы правы в том, что руководство по быстрому запуску накопителя устарело, оно относится к старой версии Библиотеки API-интерфейсов Google PHP, которая находится в коде Google, а не к новой версии GitHub. Следовательно, руководство по быстрому старту не работает с загруженной вами клиентской библиотекой PHP. Кроме того, код руководства для быстрого запуска предназначен для выполнения в режиме командной строки PHP, а не на сервере.
Чтобы ответить на вопрос, я добавил несколько ответов:
Вместо этого попробуйте использовать эту страницу: https://developers.google.com/api-client-library/php/auth/web-app, в которой показан пример отображения файлов на Google Диске Google с использованием новой библиотеки PHP, включая целая процедура OAuth.
К сожалению, даже это немного устарело (путь включения устарел и теперь устарел). Как таковой (и для полноты StackOverflow) здесь некоторый код. Я использовал подкаталог drivetest в своем корневом веб-сервере; при необходимости измените URL-адреса.
Обратите внимание, что вам нужно получить идентификатор клиента для "Веб-приложений" в консоли разработчика Google и загрузить JSON (при необходимости заменив client_secrets.json
в коде).
drivetest/quickstart.php
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
$drive_service = new Google_Service_Drive($client);
$files_list = $drive_service->files->listFiles(array())->getItems();
echo json_encode($files_list);
} else {
$redirect_uri = 'http://localhost/drivetest/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
drivetest/oauth2callback.php
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://localhost/drivetest/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_METADATA_READONLY);
if (! isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://localhost/drivetest/quickstart.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
Для вашего варианта использования вам, вероятно, лучше использовать Google Picker https://developers.google.com/picker/docs/, который реализует всю вещь для поиска и выбора файлов для вас, и просто дает идентификатор файл. Краткое изложение необходимых шагов:
Мы можем сделать это двумя способами (на стороне клиента или на стороне сервера):
Используя этот метод, шаги 1 - 3 выполняются в Javascript, и только шаг 4 выполняется в PHP. С помощью этого метода нам даже не нужна клиентская библиотека PHP!
Вот пример (адаптированный из примера кода в приведенной выше ссылке и http://webdevrefinery.com/forums/topic/12931-dropbox-google-drive-file-pickers/):
picker.html
Этот файл запускает filepicker при загрузке страницы и помещает URL-адрес в форму.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
// The Browser API key obtained from the Google Developers Console.
var developerKey = '';
// The Client ID obtained from the Google Developers Console. Replace with your own Client ID.
var clientId = ""
// Replace with your own App ID. (Its the first number in your Client ID)
var appId = ""
// Scope to use to access user Drive items.
var scope = ['https://www.googleapis.com/auth/drive'];
var pickerApiLoaded = false;
var oauthToken;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('auth', {'callback': onAuthApiLoad});
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onAuthApiLoad() {
window.gapi.auth.authorize(
{
'client_id': clientId,
'scope': scope,
'immediate': false
},
handleAuthResult);
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
function handleAuthResult(authResult) {
if (authResult && !authResult.error) {
oauthToken = authResult.access_token;
createPicker();
}
}
// Create and render a Picker object
function createPicker() {
if (pickerApiLoaded && oauthToken) {
var view = new google.picker.DocsView();
view.setIncludeFolders(true);
//view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder()
//.enableFeature(google.picker.Feature.NAV_HIDDEN)
//.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken(oauthToken)
.addView(view)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
gapi.client.load('drive', 'v2', function() {
var request = gapi.client.drive.files.get({
fileId: fileId
});
request.execute(processFile);
});
}
}
function processFile(file) {
var token = gapi.auth.getToken();
// console.log(file);
// console.log(token);
document.getElementById("fileurl").value = file.downloadUrl+"&access_token="+token.access_token;
}
</script>
</head>
<body>
<form action="submit.php" method="post">
<label for="fileurl">File Download URL</label><input type="text" name="fileurl" id="fileurl">
<input type="submit">
</form>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
<script type="text/javascript" src="https://apis.google.com/js/client.js"></script>
</body>
</html>
Затем мы передаем форму скрипту PHP для загрузки файла на сервере. Хитрость здесь заключается в том, что нам также необходимо передать токен доступа от клиента к серверу, поскольку пользователь не аутентифицирован на стороне сервера. Удивительно, но вы можете просто добавить параметр access_token
для аутентификации загрузки файла, как показано выше.
submit.php
Используйте file_get_contents
или CURL, в зависимости от того, что поддерживает ваш сервер. Для этого требуется поддержка HTTPS.
<?php
$filename = 'temp.jpg';
$ch = curl_init($_POST['fileurl']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// Should verify in production!
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
//echo 'Curl error: ' . curl_error($ch);
curl_close($ch);
file_put_contents($filename, $data);
?>
Более официальным способом (следуя https://developers.google.com/drive/web/manage-downloads#alternate_method_using_downloadurl) является отправка маркера авторизации отдельно с использованием заголовка Authorization
. Измените Javascript выше, чтобы отправить URL-адрес загрузки и токен отдельно, а затем используйте что-то вроде кода ниже. Если вы хотите использовать file_get_contents
, см. PHP file_get_contents() и заголовки о том, как отправлять пользовательские заголовки. Обратите внимание, что перед маркером необходимо иметь слово- Bearer
!
<?php
$filename = 'temp.jpg';
$ch = curl_init($_POST['fileurl']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer '.$_POST['authtoken']));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$data = curl_exec($ch);
echo 'Curl error: ' . curl_error($ch);
curl_close($ch);
file_put_contents($filename, $data);
?>
Используя этот метод, шаги 1, 3 и 4 выполняются в PHP, и только шаг 2 выполняется в Javascript.
quickstart.php
На этой странице проверяется наличие токена доступа в сеансе, если он не перенаправляет пользователя на аутентификацию. Если есть, то отображается сборщик и форма. Обратите внимание, что в коде Javascript, который используется oAuthToken, получается с PHP с сервера! Источник: используйте Google Picker без входа в аккаунт Google (с OAuth). Затем форма отправляет запрос POST на эту страницу, и файл загружается.
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
// Ref: https://developers.google.com/drive/v2/reference/files/get
function downloadFile($service, $file) {
$downloadUrl = $file->getDownloadUrl();
if ($downloadUrl) {
$request = new Google_Http_Request($downloadUrl, 'GET', null, null);
$httpRequest = $service->getClient()->getAuth()->authenticatedRequest($request);
if ($httpRequest->getResponseHttpCode() == 200) {
return $httpRequest->getResponseBody();
} else {
// An error occurred.
return null;
}
} else {
// The file doesn't have any content stored on Drive.
return null;
}
}
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->addScope(Google_Service_Drive::DRIVE_READONLY);
if (isset($_SESSION['access_token']) && $_SESSION['access_token']) {
$client->setAccessToken($_SESSION['access_token']);
if (isset($_POST['fileid'])){
$drive_service = new Google_Service_Drive($client);
$file = $drive_service->files->get($_POST['fileid']);
$data = downloadFile($drive_service, $file);
file_put_contents('temp.jpg', $data);
echo "file uploaded";
exit();
}
} else {
$redirect_uri = 'http://localhost/drivepicker-php/oauth2callback.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
exit();
}
?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Google Picker Example</title>
<script type="text/javascript">
// The Browser API key obtained from the Google Developers Console.
var developerKey = '';
// Replace with your own App ID. (Its the first number in your Client ID)
var appId = ""
var pickerApiLoaded = false;
// Use the Google API Loader script to load the google.picker script.
function loadPicker() {
gapi.load('picker', {'callback': onPickerApiLoad});
}
function onPickerApiLoad() {
pickerApiLoaded = true;
createPicker();
}
// Create and render a Picker object
function createPicker() {
if (pickerApiLoaded) {
var view = new google.picker.DocsView();
view.setIncludeFolders(true);
//view.setMimeTypes("image/png,image/jpeg,image/jpg");
var picker = new google.picker.PickerBuilder()
//.enableFeature(google.picker.Feature.NAV_HIDDEN)
//.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.setAppId(appId)
.setOAuthToken('<?= json_decode($client->getAccessToken())->access_token; ?>')
.addView(view)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
}
}
// A simple callback implementation.
function pickerCallback(data) {
if (data.action == google.picker.Action.PICKED) {
var fileId = data.docs[0].id;
document.getElementById("fileid").value = fileId;
}
}
</script>
</head>
<body>
<form action="quickstart.php" method="post">
<label for="fileid">File ID</label><input type="text" name="fileid" id="fileid">
<input type="submit">
</form>
<!-- The Google API Loader script. -->
<script type="text/javascript" src="https://apis.google.com/js/api.js?onload=loadPicker"></script>
<script type="text/javascript" src="https://apis.google.com/js/client.js"></script>
</body>
</html>
oauth2callback.php
Вспомогательный файл для обратного вызова OAuth.
<?php
require_once 'google-api-php-client/src/Google/autoload.php';
session_start();
$client = new Google_Client();
$client->setAuthConfigFile('client_secrets.json');
$client->setRedirectUri('http://localhost/drivepicker-php/oauth2callback.php');
$client->addScope(Google_Service_Drive::DRIVE_READONLY);
if (!isset($_GET['code'])) {
$auth_url = $client->createAuthUrl();
header('Location: ' . filter_var($auth_url, FILTER_SANITIZE_URL));
} else {
$client->authenticate($_GET['code']);
$_SESSION['access_token'] = $client->getAccessToken();
$redirect_uri = 'http://localhost/drivepicker-php/quickstart.php';
header('Location: ' . filter_var($redirect_uri, FILTER_SANITIZE_URL));
}
?>
client_secrets.json
с console.developers.google.com (где вы получаете свои идентификаторы и секрет). Существует опция «Загрузить JSON» после создания идентификатора клиента. Он не будет называться client_secrets.json
, но просто переименуйте его или измените значение переменной по client_secrets.json
. Как примечание, этот файл json должен быть секретным и не должен находиться в каталоге, доступном через Интернет, в производственной среде.