feat(upload): фото и файлы отдельными путями на Android
This commit is contained in:
1 parent
19547d1797
commit
21f8fbb6a4
6 files changed
+128
-6
No files matched your search
+15
-5
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
require __DIR__ . '/browser-upload.php';
|
||||
|
||||
$errorMessage = Yii::t('app', 'Возникла ошибка');
|
||||
$utmJson = json_encode($UTM ?? [], JSON_UNESCAPED_UNICODE);
|
||||
@@ -11,7 +12,7 @@ $basePickerAccept = 'image/jpeg,image/png,image/gif,image/webp,image/bmp,image/a
|
||||
|
||||
?>
|
||||
|
||||
<form action="<?= htmlspecialchars($createApiUrl, ENT_QUOTES, 'UTF-8') ?>" class="dropzone-form gradient-dashed-border" id="dropzone-form" method="POST" style="background: transparent; border: unset; display: <?= ($show ?? true) ? '' : 'none'; ?>; cursor: pointer;">
|
||||
<form action="<?= htmlspecialchars($createApiUrl, ENT_QUOTES, 'UTF-8') ?>" class="dropzone-form gradient-dashed-border" id="dropzone-form" data-photo-label="<?= htmlspecialchars(Yii::t('app', 'Выбрать фото'), ENT_QUOTES, 'UTF-8') ?>" method="POST" style="background: transparent; border: unset; display: <?= ($show ?? true) ? '' : 'none'; ?>; cursor: pointer;">
|
||||
|
||||
<div class="dropzone-form-inner">
|
||||
<div class="dropzone-form-icon">
|
||||
@@ -26,7 +27,7 @@ $basePickerAccept = 'image/jpeg,image/png,image/gif,image/webp,image/bmp,image/a
|
||||
<div class="dropzone-form-format-item">HEIC</div>
|
||||
<div class="dropzone-form-format-item">WebP</div>
|
||||
<div class="dropzone-form-format-item">GIF</div>
|
||||
<div class="dropzone-form-format-item">PDF</div>
|
||||
<div class="dropzone-form-format-item" data-format-optional>PDF</div>
|
||||
<div class="dropzone-form-format-item">+много</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -37,6 +38,7 @@ $basePickerAccept = 'image/jpeg,image/png,image/gif,image/webp,image/bmp,image/a
|
||||
<path d="M13.3333 14.6667C15.6345 14.6667 17.5 12.8012 17.5 10.5C17.5 8.43079 15.9917 6.71387 14.0145 6.38874C14.0113 6.38821 14.0086 6.38583 14.0078 6.38267C13.4802 4.43373 11.6992 3 9.58333 3C7.05203 3 5 5.05203 5 7.58333C5 7.75477 5.00941 7.924 5.02775 8.09055C5.0282 8.0947 5.0255 8.09856 5.02145 8.09957C3.57289 8.4621 2.5 9.77242 2.5 11.3333C2.5 13.1743 3.99238 14.6667 5.83333 14.6667H6.66667M10 8.83726V18M10 8.83726L7.5 11.3333M10 8.83726L12.5 11.3333" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<?php require __DIR__ . '/upload-picker-links.php'; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -78,14 +80,16 @@ $basePickerAccept = 'image/jpeg,image/png,image/gif,image/webp,image/bmp,image/a
|
||||
// отправляется в content-based Tour gate, где и показывается controlled error.
|
||||
let pickerAccept = <?= json_encode($basePickerAccept, JSON_UNESCAPED_UNICODE) ?>;
|
||||
let maxUploadBytes = 0;
|
||||
window.ZoomzillaUpload.bindPicker(formEl, fileInput, () => pickerAccept, files => handleSelectedFile(files[0]));
|
||||
if (uploadPolicyApiUrl && window.fetch) {
|
||||
fetch(uploadPolicyApiUrl, { credentials: 'omit', cache: 'no-store' })
|
||||
.then(response => response.ok ? response.json() : null)
|
||||
.then(policy => {
|
||||
if (typeof policy?.picker_accept === 'string' && policy.picker_accept !== '') {
|
||||
pickerAccept = policy.picker_accept;
|
||||
fileInput.accept = pickerAccept;
|
||||
fileInput.accept = /Android/i.test(navigator.userAgent) ? 'image/*' : pickerAccept;
|
||||
}
|
||||
if (policy?.pdf_observation_enabled === false) formEl.querySelector('[data-files-picker]').textContent = <?= json_encode(Yii::t('app', 'Выбрать файлы (другие форматы)'), JSON_UNESCAPED_UNICODE) ?>;
|
||||
if (Number.isSafeInteger(policy?.max_file_size_bytes) && policy.max_file_size_bytes > 0) {
|
||||
maxUploadBytes = policy.max_file_size_bytes;
|
||||
}
|
||||
@@ -124,7 +128,7 @@ $basePickerAccept = 'image/jpeg,image/png,image/gif,image/webp,image/bmp,image/a
|
||||
uploadPending = false;
|
||||
if (uploadDotsTimer !== null) window.clearInterval(uploadDotsTimer);
|
||||
uploadDotsTimer = null;
|
||||
if (uploadButtonLabel) uploadButtonLabel.textContent = uploadButtonDefaultLabel;
|
||||
if (uploadButtonLabel) uploadButtonLabel.textContent = uploadButtonLabel.dataset.pickerLabel || uploadButtonDefaultLabel;
|
||||
if (uploadButton) {
|
||||
uploadButton.disabled = false;
|
||||
uploadButton.removeAttribute('aria-busy');
|
||||
@@ -217,12 +221,18 @@ $basePickerAccept = 'image/jpeg,image/png,image/gif,image/webp,image/bmp,image/a
|
||||
}
|
||||
|
||||
function uploadFile(file) {
|
||||
// Тот же обход нестабильного Android FileProvider, что на основном сайте.
|
||||
window.ZoomzillaUpload.prepare(file, maxUploadBytes || 15 * 1024 * 1024)
|
||||
.then(bytes => uploadPreparedFile(file, bytes))
|
||||
.catch(() => showUploadError(genericErrorMsg));
|
||||
}
|
||||
function uploadPreparedFile(file, bytes) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
const formData = new FormData();
|
||||
// Ключ загрузки: по нему сайт передаёт её в сессию посетителя (/api/images/public/claim, годен 30 мин).
|
||||
// randomUUID есть в HTTPS-контексте; где его нет (старый Safari), есть getRandomValues.
|
||||
const clientKey = createClientKey();
|
||||
formData.append('file', file);
|
||||
formData.append('file', bytes, file.name || 'upload');
|
||||
formData.append('client_key', clientKey);
|
||||
|
||||
const actionUrl = createApiUrl || formEl.getAttribute('action') || '/api/images/public/create';
|
||||
|
||||
Reference in new issue
Block a user