Я выполнил следующие шаги, чтобы опубликовать файл PDF в Drupal.
Включите JSON API для создания в admin/config/services/jsonapi.
Включить медиа-ресурс POST
Медиа /media/{media}/edit: ПОЛУЧИТЬ, ИСПРАВИТЬ, УДАЛИТЬ
/entity/media: POST
Методы: POST, форматы: json: аутентификация: cookie
Создайте приложение Angular и вставьте его на страницу Drupal в виде блока.
Приложение Angular захватывает страницу с помощью jspdf и встраивает изображение в PDF. Вместо использования перехватчика я получаю токен с каждым запросом.
this.certificateService.getCsrf().subscribe(токен => {
this.certificateService.uploadMedia(pdf.output('blob'), fileName, token).subscribe({
завершено: () => {
console.log('размещенные медиафайлы');
}
})
});
получитьCsrf()
захватывает токен в виде текста.
getCsrf(): Наблюдаемый<строка> {
const headers = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8');
вернуть this.httpClient.get(this.host + '/session/token', {заголовки: заголовки, responseType: 'text'}).pipe(catchError(this.handleError<any>('token')))
}
загрузитьМедиа()
пытается опубликовать файл PDF на носителе в Drupal.
uploadMedia(pdf: Blob, name: string, token: string): Observable<any> {
const formData: FormData = new FormData();
formData.append('сертификат', pdf, имя);
константные заголовки = новые HttpHeaders();
headers.set('Принять', 'application/vnd.api+json');
headers.set('X-CSRF-токен', токен);
// headers.set('Content-Type','application/octet-stream');
headers.set('Content-Type','application/hal+json');
headers.set('Content-Disposition',`file; filename=${name}`);
вернуть this.httpClient.post(this.host + '/entity/media', formData, {headers: headers})
.трубка(
catchError(this.handleError<любой>('uploadMedia'))
);
}
Ошибка, которую я получаю, 415 Неподдерживаемый тип носителя.
Я использую Angular 13 и Drupal 9.
Я посмотрел журнал ошибок Drupal; он сообщает о следующем исключении.
Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException: не найден маршрут, соответствующий "Content-Type: multipart/form-data; border=----WebKitFormBoundaryYAzO5lNTfgLQwQq9" в Drupal\Core\Routing\ContentTypeHeaderMatcher->filter()
Просто установка заголовка Content-Type не всегда изменяет публикуемый заголовок типа контента. например Как с axios, так и с angular http, если вы публикуете Данные формы array, вы получите форму, состоящую из нескольких частей, даже если заголовок на уровне вызова является приложением/октетным потоком
Использование axios в angular следующим образом приводит к «application/octet-stream»:
импортировать Axios из 'axios-observable';
Axios.defaults.headers.post['X-CSRF-Token'] = токен;
вернуть Axios.post(this.host + '/entity/media', pdf, {
заголовки: {
Принять: `application/json, text/plain, */*',
Авторизация: `Basic ${basic}`,
Файл cookie: ${cookie}; XDEBUG_SESSION=13681',
'Content-Type': 'application/octet-stream',
}
});
Передача необработанных данных PDF приводит к «application/pdf»
константные заголовки = новые HttpHeaders();
headers.set('Content-Type', 'application/octet-stream');
вернуть this.httpClient.post(this.host + '/entity/media', pdf, {заголовки: заголовки})
.трубка(
catchError(this.handleError<любой>('uploadMedia'))
);
Просмотр страницы остальных услуг админ/конфиг/сервисы/отдых, допустимый формат содержимого — json.
Отладка подтверждает, что Symfony проверяет это значение
Попытка интерфейса REST, т.е. '/jsonapi/media/document/field_media_document/'
Да, в файле web/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php есть требование типа содержимого «bin», которое
// Добавляем проверку доступа к формату типа контента. Это обеспечит соблюдение всех
// входящие запросы могут использовать только 'application/octet-stream'
// Заголовок Content-Type.
/объект/медиа URL-адрес запроса JSON API требует запроса JSON в соответствии с web/core/lib/Drupal/Core/Routing/ContentTypeHeaderMatcher.php