|
1 | 1 | // From |
2 | 2 | // https://ckeditor.com/docs/ckeditor5/latest/framework/guides/deep-dive/upload-adapter.html |
3 | 3 |
|
| 4 | +import documentsService from "../../services/documents" |
| 5 | + |
4 | 6 | export default class MyUploadAdapter { |
5 | 7 | constructor(loader) { |
6 | 8 | // The file loader instance to use during the upload. |
7 | 9 | this.loader = loader |
| 10 | + // Allows aborting the in-flight request from abort(). |
| 11 | + this.controller = new AbortController() |
8 | 12 | } |
9 | 13 |
|
10 | 14 | // Starts the upload process. |
11 | 15 | upload() { |
12 | | - return this.loader.file.then( |
13 | | - (file) => |
14 | | - new Promise((resolve, reject) => { |
15 | | - this._initRequest() |
16 | | - this._initListeners(resolve, reject, file) |
17 | | - this._sendRequest(file) |
18 | | - }), |
19 | | - ) |
| 16 | + return this.loader.file.then((file) => this._sendRequest(file)) |
20 | 17 | } |
21 | 18 |
|
22 | 19 | // Aborts the upload process. |
23 | 20 | abort() { |
24 | | - if (this.xhr) { |
25 | | - this.xhr.abort() |
26 | | - } |
27 | | - } |
28 | | - |
29 | | - // Initializes the XMLHttpRequest object using the URL passed to the constructor. |
30 | | - _initRequest() { |
31 | | - const xhr = (this.xhr = new XMLHttpRequest()) |
32 | | - |
33 | | - // Note that your request may look different. It is up to you and your editor |
34 | | - // integration to choose the right communication channel. This example uses |
35 | | - // a POST request with JSON as a data structure but your configuration |
36 | | - // could be different. |
37 | | - xhr.open("POST", "/api/documents", true) |
38 | | - xhr.responseType = "json" |
| 21 | + this.controller.abort() |
39 | 22 | } |
40 | 23 |
|
41 | | - // Initializes XMLHttpRequest listeners. |
42 | | - _initListeners(resolve, reject, file) { |
43 | | - const xhr = this.xhr |
44 | | - const loader = this.loader |
| 24 | + // Prepares the data and sends the request through the documents service. |
| 25 | + async _sendRequest(file) { |
45 | 26 | const genericErrorText = `Couldn't upload file: ${file.name}.` |
| 27 | + const loader = this.loader |
46 | 28 |
|
47 | | - xhr.addEventListener("error", () => reject(genericErrorText)) |
48 | | - xhr.addEventListener("abort", () => reject()) |
49 | | - xhr.addEventListener("load", () => { |
50 | | - const response = xhr.response |
51 | | - |
52 | | - // This example assumes the XHR server's "response" object will come with |
53 | | - // an "error" which has its own "message" that can be passed to reject() |
54 | | - // in the upload promise. |
55 | | - // |
56 | | - // Your integration may handle upload errors in a different way so make sure |
57 | | - // it is done properly. The reject() function must be called when the upload fails. |
58 | | - if (!response || response.error) { |
59 | | - return reject(response && response.error ? response.error.message : genericErrorText) |
60 | | - } |
61 | | - |
62 | | - // If the upload is successful, resolve the upload promise with an object containing |
63 | | - // at least the "default" URL, pointing to the image on the server. |
64 | | - // This URL will be used to display the image in the content. Learn more in the |
65 | | - // UploadAdapter#upload documentation. |
66 | | - resolve({ |
67 | | - //default: response.url |
68 | | - default: response.contentUrl, |
69 | | - }) |
70 | | - }) |
71 | | - |
72 | | - // Upload progress when it is supported. The file loader has the #uploadTotal and #uploaded |
73 | | - // properties which are used e.g. to display the upload progress bar in the editor |
74 | | - // user interface. |
75 | | - if (xhr.upload) { |
76 | | - xhr.upload.addEventListener("progress", (evt) => { |
77 | | - if (evt.lengthComputable) { |
78 | | - loader.uploadTotal = evt.total |
79 | | - loader.uploaded = evt.loaded |
80 | | - } |
81 | | - }) |
82 | | - } |
83 | | - } |
84 | | - |
85 | | - // Prepares the data and sends the request. |
86 | | - _sendRequest(file) { |
87 | 29 | // Prepare the form data. |
88 | 30 | const data = new FormData() |
89 | 31 |
|
90 | 32 | // Chamilo |
91 | 33 | data.append("filetype", "file") |
92 | 34 | data.append("parentResourceNodeId", "4") |
93 | | - //data.append('resourceLinkList', '{"cid": 1, "visibility":2}'); |
94 | 35 | data.append("uploadFile", file) |
95 | | - //data.append( 'upload', file ); |
96 | 36 |
|
97 | | - // Important note: This is the right place to implement security mechanisms |
98 | | - // like authentication and CSRF protection. For instance, you can use |
99 | | - // XMLHttpRequest.setRequestHeader() to set the request headers containing |
100 | | - // the CSRF token generated earlier by your application. |
| 37 | + try { |
| 38 | + const response = await documentsService.uploadDocumentFile(data, { |
| 39 | + signal: this.controller.signal, |
| 40 | + // The file loader has the #uploadTotal and #uploaded properties which are |
| 41 | + // used e.g. to display the upload progress bar in the editor user interface. |
| 42 | + onUploadProgress: (evt) => { |
| 43 | + if (evt.lengthComputable) { |
| 44 | + loader.uploadTotal = evt.total |
| 45 | + loader.uploaded = evt.loaded |
| 46 | + } |
| 47 | + }, |
| 48 | + }) |
101 | 49 |
|
102 | | - // Send the request. |
103 | | - this.xhr.send(data) |
| 50 | + if (!response || response.error) { |
| 51 | + throw new Error(response && response.error ? response.error.message : genericErrorText) |
| 52 | + } |
| 53 | + |
| 54 | + // Resolve the upload promise with an object containing at least the "default" |
| 55 | + // URL, pointing to the image on the server. This URL is used to display the |
| 56 | + // image in the content. |
| 57 | + return { default: response.contentUrl } |
| 58 | + } catch (error) { |
| 59 | + const apiMessage = error?.response?.data?.error?.message |
| 60 | + throw new Error(apiMessage || error?.message || genericErrorText, { cause: error }) |
| 61 | + } |
104 | 62 | } |
105 | 63 | } |
0 commit comments