ฉันทำตามขั้นตอนเหล่านี้เพื่อโพสต์ไฟล์ PDF ไปยัง Drupal
เปิดใช้ JSON API เพื่อสร้างที่ admin/config/services/jsonapi
เปิดใช้งานทรัพยากรสื่อ POST
สื่อ /media/{media}/edit: GET, PATCH, DELETE
/เอนทิตี/สื่อ: POST
วิธีการ: POST, รูปแบบ: json: การรับรองความถูกต้อง: คุกกี้
สร้างแอปพลิเคชันเชิงมุมและฝังลงในหน้า Drupal เป็นบล็อก
แอปพลิเคชันเชิงมุมจับภาพหน้าโดยใช้ jspdf และฝังรูปภาพใน PDF แทนที่จะใช้ตัวสกัดกั้น ฉันได้รับโทเค็นในแต่ละคำขอ
this.certificateService.getCsrf().subscribe(โทเค็น => {
this.certificateService.uploadMedia(pdf.output('blob'), fileName, token).subscribe({
สมบูรณ์: () => {
console.log('สื่อที่โพสต์');
}
})
});
getCsrf()
คว้าโทเค็นเป็นข้อความ
getCsrf (): สังเกตได้ <string> {
ส่วนหัวของ const = new HttpHeaders().set('Content-Type', 'text/plain; charset=utf-8');
ส่งคืน this.httpClient.get(this.host + '/session/token',{ headers: headers, responseType: 'text'}).pipe(catchError(this.handleError<any>('token')))
}
อัปโหลดสื่อ ()
พยายามโพสต์ไฟล์ PDF ไปยังสื่อไปยัง Drupal
uploadMedia(pdf: Blob, ชื่อ: string, token: string): Observable<any> {
Const formData: FormData = ใหม่ FormData();
formData.append('ใบรับรอง', pdf, ชื่อ);
ส่วนหัว const = HttpHeaders ใหม่ ();
headers.set('ยอมรับ', 'application/vnd.api+json');
headers.set('X-CSRF-โทเค็น',โทเค็น);
// headers.set('Content-Type','application/octet-stream');
headers.set('ประเภทเนื้อหา','application/hal+json');
headers.set('การจัดการเนื้อหา',`file; filename=${name}`);
ส่งคืน this.httpClient.post (this.host + '/entity/media', formData, {ส่วนหัว: ส่วนหัว})
.ท่อ(
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()
การตั้งค่าส่วนหัวของประเภทเนื้อหาไม่ได้เปลี่ยนส่วนหัวของประเภทเนื้อหาที่โพสต์เสมอไป เช่น. ด้วย axios และ http เชิงมุมหากคุณโพสต์ไฟล์ ข้อมูลแบบฟอร์ม อาร์เรย์ คุณจะได้รับแบบฟอร์มหลายส่วน แม้ว่าส่วนหัวของคุณในระดับการโทรจะเป็น application/octet-stream
การใช้ axios ภายในเชิงมุมจะส่งผลให้ '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}`,
คุกกี้: ${คุกกี้}; XDEBUG_SESSION=13681',
'ประเภทเนื้อหา': 'แอปพลิเคชัน/ออคเต็ตสตรีม'
}
});
การส่งผ่านข้อมูล PDF ดิบจะส่งผลให้เป็น 'application/pdf'
ส่วนหัว const = HttpHeaders ใหม่ ();
headers.set('ประเภทเนื้อหา', 'แอปพลิเคชัน/octet-stream');
ส่งคืน this.httpClient.post(this.host + '/entity/media', pdf, {ส่วนหัว: headers})
.ท่อ(
catchError(this.handleError<ใดๆ>('uploadMedia'))
);
ตรวจสอบหน้าบริการส่วนที่เหลือ ผู้ดูแลระบบ/config/services/restรูปแบบเนื้อหาที่อนุญาตคือ 'json'
การดีบักยืนยันว่า symfony กำลังตรวจสอบค่านี้
ลองใช้อินเทอร์เฟซ REST เช่น '/jsonapi/media/document/field_media_document/'
ใช่ มีข้อกำหนดประเภทเนื้อหา 'bin' ใน web/core/modules/file/src/Plugin/rest/resource/FileUploadResource.php ซึ่ง
// เพิ่มการตรวจสอบการเข้าถึงรูปแบบประเภทเนื้อหา สิ่งนี้จะบังคับใช้ทั้งหมด
// คำขอที่เข้ามาสามารถใช้ได้เฉพาะ 'application/octet-stream'
// ส่วนหัวของประเภทเนื้อหา
เดอะ /เอนทิตี/สื่อ URL คำขอ JSON API ไม่ต้องการคำขอ JSON ตาม เว็บ/core/lib/Drupal/Core/Routing/ContentTypeHeaderMatcher.php