Am urmat acești pași pentru a posta un fișier PDF pe Drupal.
Activați API-ul JSON pentru a crea la admin/config/services/jsonapi
Activați resursa media POST
Media /media/{media}/edit: GET, PATCH, DELETE
/entity/media: POST
Metode: POST, formate: json: autentificare: cookie
Creați o aplicație Angular și încorporați-o în pagina Drupal ca bloc
Aplicația Angular captează pagina folosind jspdf și încorporează imaginea în PDF. În loc să folosesc un interceptor, primesc un token la fiecare cerere.
this.certificateService.getCsrf().subscribe(token => {
this.certificateService.uploadMedia(pdf.output('blob'), fileName, token).subscribe({
complet: () => {
console.log('media postată');
}
})
});
getCsrf()
ia jetonul ca text.
getCsrf(): Observabil<șir> {
const headers = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8');
return this.httpClient.get(this.host + '/session/token',{ headers: headers, responseType: 'text'}).pipe(catchError(this.handleError<any>('token')))
}
uploadMedia()
încearcă să posteze fișierul PDF pe media la Drupal.
uploadMedia(pdf: Blob, nume: șir, indicativ: șir): Observabil<orice> {
const formData: FormData = new FormData();
formData.append('certificat', pdf, nume);
const headers = new HttpHeaders();
headers.set('Accept', 'application/vnd.api+json');
headers.set('X-CSRF-Token',token);
// headers.set('Content-Type','application/octet-stream');
headers.set('Content-Type','application/hal+json');
headers.set('Content-Disposition',`file; filename=${name}`);
returnează this.httpClient.post(this.host + '/entity/media', formData, {headers: headers})
.pipe(
catchError(this.handleError<any>('uploadMedia'))
);
}
Eroarea pe care o primesc este 415 Tip media neacceptat.
Folosesc Angular 13 și Drupal 9.
M-am uitat la jurnalul de erori Drupal; raportează următoarea excepție.
Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException: Nu s-a găsit nicio rută care să se potrivească cu „Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryYAzO5lNTfgLQwQq9” în Drupal\Core\Typeter(ContentMatcher)->ater
Doar setarea antetului Content-Type nu modifică întotdeauna antetul tipului de conținut care este postat. de exemplu. Cu atât axios, cât și unghiular http dacă postați a FormData matrice, veți obține un formular cu mai multe părți, chiar dacă antetul la nivel de apel este aplicație/flux-octet
Folosind axios în unghiular, după cum urmează, rezultă „application/octet-stream”:
import Axios din 'axios-observable';
Axios.defaults.headers.post['X-CSRF-Token'] = simbol;
returnează Axios.post(this.host + '/entity/media', pdf, {
antete: {
Accept: `application/json, text/plain, */*',
Autorizare: `Basic ${basic}`,
Cookie: ${cookie}; XDEBUG_SESSION=13681',
„Content-Type”: „application/octet-stream”,
}
});
Transmiterea datelor PDF brute are ca rezultat „aplicație/pdf”
const headers = new HttpHeaders();
headers.set('Content-Type', 'application/octet-stream');
returnează this.httpClient.post(this.host + '/entity/media', pdf, {headers: headers})
.pipe(
catchError(this.handleError<any>('uploadMedia'))
);
Revizuirea paginii de servicii de rest admin/config/services/rest, formatul de conținut permis este „json”
Depanarea confirmă că symfony verifică această valoare
Încercarea unei interfețe REST, adică „/jsonapi/media/document/field_media_document/”
Da, există o cerință de tip de conținut „bin” în web/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php care
// Adăugați verificarea accesului la formatul tipului de conținut. Acest lucru va impune toate acestea
// cererile primite pot folosi numai „aplicația/octet-stream”
// Antetul Content-Type.
The /entity/media URL-ul solicitării API JSON are nevoie de o solicitare JSON conform web/core/lib/Drupal/Core/Routing/ContentTypeHeaderMatcher.php