Puncte:0

Cum postez un PDF?

drapel km

Am urmat acești pași pentru a posta un fișier PDF pe Drupal.

  1. Activați API-ul JSON pentru a crea la admin/config/services/jsonapi

  2. Activați resursa media POST

    Media /media/{media}/edit: GET, PATCH, DELETE
          /entity/media: POST
    
    Metode: POST, formate: json: autentificare: cookie
    
  3. 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.

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

Symfony acceptă JSON

Î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

cerere json media entității

Puncte:0
drapel cn

Folosesc Angular, nu React, dar sunt destul de sigur că această parte este greșită:

  // headers.set('Content-Type','application/octet-stream');
  headers.set('Content-Type','application/hal+json');

Fișierele trebuie postate ca aplicație/flux-octet. Nu este un obiect JSON; este un dosar.

De asemenea, poate fi necesar să masați datele PDF în ceva pe care JSON:API îl înțelege. De exemplu, iată documentele despre a face acest lucru cu axios/Node.js.

În cazul meu, pentru fișierele imagine, a trebuit să citesc fișierul ca blob (codul React, dar poate oferi un exemplu):

// https://stackoverflow.com/a/46568146
funcția readFileBlob(fileBlob: Blob) {
  returnează promisiune nouă((rezolvare) => {
    const reader = new FileReader();
    reader.onload = () => {
      rezolvare(cititor.rezultat);
    };
    reader.onabort = () => Promise.reject(Eroare('citirea fișierului a fost anulată'));
    reader.onerror = () => Promise.reject(Eroare('citirea fișierului a eșuat'));
    reader.readAsArrayBuffer(fileBlob);
  });
}

// fileToPost este un șir care conține un blob:
// blob:http://localhost:8100/00507d3e-7f6f-4f48-be80-b55c8bc20dd3
const postAuthFileBlob = asincron (
  fetchUrl: șir,
  fileToPost: șir,
  // Fetch poate returna orice.
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
): Promit<orice> => {
  const fileBlob = await fetch(fileToPost).then((res) => res.blob());
  const arrayStr = (așteptați readFileBlob(fileBlob)) ca ArrayBuffer;
  return postAuthFileBlobPart2(fetchUrl, arrayStr);
};
Interlated avatar
drapel km
Cred că ești aproape. Back-end-ul se plânge că tipul de conținut este multipart/form-data în loc de application/octet-stream
Interlated avatar
drapel km
Doar postarea pdf-ului dă cerere/pdf return this.httpClient.post(this.host + '/entity/media', pdf, {headers: headers}). Totuși, drupal nu poate găsi o potrivire pentru aplicație/pdf. Nu s-a găsit nicio rută care să se potrivească cu „Content-Type: application/pdf” în Drupal\Core\Routing\ContentTypeHeaderMatcher->filter() (linia 49 din
drapel cn
@Interlated După cum am spus deja, trebuie să postați ca „application/octet-stream”. Din anumite motive, ați comentat asta în codul dvs., dar trebuie să postați ca `application/octet-stream` dacă doriți să încărcați fișiere binare.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.