Как загрузить файлы через API?

Я пытаюсь разобраться, как разрешить загрузку файлов через API. Я видел этот полезный пост: How to upload a file via API and get it's URL? - #3 by Daniil_Bazhenov,

но в нём нет реального синтаксиса — именно с этим у меня возникают трудности. У кого-нибудь есть реальный синтаксис для AJAX-вызова?

Вот что у меня получилось:

 method: "post",
      url: [site]/uploads.json,
      contentType: "multipart/form-data",
      data: {
        type: "composer",
        file: '/path_to_file_from_users_machine'
      },
      headers: {
        "User-Api-Key": key
      },
      dataType: "json",
    }).then((result)=>{

Но это возвращает ответ 422 — в этом синтаксисе что-то не так. Как мне заставить это работать?

Есть ли какое-то сообщение, сопровождающее этот ответ? Оно должно предоставить вам больше информации.

Насколько я могу судить, это единственная реакция:
Error: Request failed with status code 422

И в логах я ничего не вижу.

Вот пример на Node.js, который кому-то удалось запустить и который может помочь:

Большое спасибо, @blake. Это полезный пост, который я раньше не видел (несмотря на то, что искал что-то подобное). Он точно поможет мне продвинуться дальше. Однако одна вещь привлекла моё внимание. Эта строка в связанном коде:
const file = fs.readFileSync(filename);

Эта строка подразумевает, что то, что вы загружаете в Discourse, — это не сам файл, а его содержимое (в приведённом коде переменная file = строка, возвращаемая при чтении файла). Это для меня удивительно, и я задаюсь вопросом, что это означает для загрузки бинарных файлов (или медиафайлов — они загружаются в Discourse напрямую без проблем, если размер в допустимых пределах, но неясно, как будет работать их предварительное чтение).

Но я разберусь с этим.

Всем привет, после некоторых трудностей и проб и ошибок я решил поделиться рабочим примером на PHP для загрузки файлов в Discourse! Вот он. Также я обновляю библиотеку, изначально созданную communiteq/discourse-api-php: PHP API client for Discourse (github.com):

<?php
	
	$curl = curl_init();
	
	curl_setopt_array($curl, array(
		CURLOPT_URL => 'https://example.com/uploads.json',
		CURLOPT_RETURNTRANSFER => true,
		CURLOPT_ENCODING => '',
		CURLOPT_MAXREDIRS => 10,
		CURLOPT_TIMEOUT => 0,
		CURLOPT_FOLLOWLOCATION => true,
		CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
		CURLOPT_CUSTOMREQUEST => 'POST',
		CURLOPT_POSTFIELDS => array(
			'type' => 'composer',
			'synchronous' => 'true',
			'file'=> new CURLFILE('/directory/filename.txt')),
		CURLOPT_HTTPHEADER => array(
			'Content-Type: multipart/form-data',
			'Accept: application/json',
			'Api-Key: <your api key>',
			'Api-Username: <your api user id>'
		),
	));
	
	$response = curl_exec($curl);
	$info = curl_getinfo($curl);
	curl_close($curl);
	print_r(json_decode($response,1));
	print_r($info);
?>

Пример вывода:

Array
(
    [id] => 627
    [url] => https://example.com/uploads/default/original/1X/4661e3a873857e04440bcc3e4290e241eb6c08d7.txt
    [original_filename] => filename.txt
    [filesize] => 461
    [width] => 
    [height] => 
    [thumbnail_width] => 
    [thumbnail_height] => 
    [extension] => txt
    [short_url] => upload://a2D9hHsjwsdrVWkzlu5Go4c1VvV.txt
    [short_path] => /uploads/short-url/a2D9hHsjwsdrVWkzlu5Go4c1VvV.txt
    [retain_hours] => 
    [human_filesize] => 461 Bytes
    [dominant_color] => 
    [thumbnail] => 
)
Array
(
    [url] => https://example.com/uploads.json
    [content_type] => application/json; charset=utf-8
    [http_code] => 200
    [header_size] => 422
    [request_size] => 1244
    [filetime] => -1
    [ssl_verify_result] => 0
    [redirect_count] => 0
    [total_time] => 0.029617
    [namelookup_time] => 0.00046
    [connect_time] => 0.003265
    [pretransfer_time] => 0.003592
    [size_upload] => 911
    [size_download] => 460
    [speed_download] => 15531
    [speed_upload] => 30759
    [download_content_length] => 460
    [upload_content_length] => 911
    [starttransfer_time] => 0.029604
    [redirect_time] => 0
    [redirect_url] => 
    [primary_ip] => 192.168.192.40
    [certinfo] => Array
        (
        )

    [primary_port] => 80
    [local_ip] => 192.168.192.18
    [local_port] => 61613
    [http_version] => 2
    [protocol] => 1
    [ssl_verifyresult] => 0
    [scheme] => http
    [appconnect_time_us] => 0
    [connect_time_us] => 3265
    [namelookup_time_us] => 460
    [pretransfer_time_us] => 3592
    [redirect_time_us] => 0
    [starttransfer_time_us] => 29604
    [total_time_us] => 29617
    [effective_method] => POST
    [capath] => 
    [cainfo] => 
)

Также огромная благодарность за примеры из Postman здесь: Creates an upload | Discourse | Postman API Network

Удачи!