Jump to content

Проблема с загрузкой файлов по REST API

Featured Replies

comment_198715

001 а у вас-то это работает? Или на лету изобретаете?

Сейчас NO_FILES

3 минуты назад, MrShandy сказал:

Зачем его открытым то держать пока запрос выполняется? 

Да это не принципиально для отладки. 

  • Author
comment_198716
Только что, Desti сказал:

001 а у вас-то это работает? Или на лету изобретаете?

 

Есть ощущение, что это какая то нейронка пишет)

  • 8 месяцев спустя...
  • Author
comment_211340

И вновь вернулся к этой теме, не даёт мне покоя загрузка. Может кто то всё таки придумал как можно загрузить по стандартному эндпоинту?

comment_211342
В 06.01.2024 в 16:07, MrShandy сказал:

Не совсем понимаю как мне загружать файлы по REST API. Написал скрипт на python для загрузки, но как бы я не пробовал, ничего не получается. Если кто то делал, можете подсказать как именно отправляли файлы?

Вот скрипт, может я в чем то ошибаюсь? Хотя мы с напарником многое перепробовали уже и пока никаких результатов.

  Скрыть контент
import asyncio

import aiohttp

url = 'https://scrapmechanic.ru/api/downloads/files'
token = 'API KEY'
params = {
    'category': 5,
    'author': 1,
    'title': 'archive.zip',
    'description': '<p>This is an archive file.</p>',
    'hidden': 1,
}


async def upload_file(data_files: dict):
    auth = aiohttp.BasicAuth(token, "")
    async with aiohttp.ClientSession(auth=auth) as session:
        print("Params:")
        print(params)
        print("Data:")
        print(data_files)
        async with session.post(url, params=params, data=data_files) as response:
            print("Headers:")
            print(response.request_info.headers)
            print("Response JSON:")
            print(await response.json())
            print("Response text:")
            print(await response.text())
            print("Response status:")
            print(response.status)
            print("Response content-type:")
            print(response.content_type)
            print("=" * 10)
            if response.ok:
                print('File uploaded successfully.')
            else:
                print('Failed to upload file. Error:', await response.text())


async def main():
    file_content = open('archive.zip', 'rb')
    data_files = {
        "archive.zip": [file_content.read()],
    }
    params['files'] = [key for key in data_files.keys()]
    await upload_file(data_files)
    file_content.close()


loop = asyncio.new_event_loop()
loop.run_until_complete(main())

Вот часть кода API, ориентировался на него когда писал скрипт.

  Скрыть контент
	/**
	 * POST /downloads/files
	 * Upload a file
	 *
	 * @note	For requests using an OAuth Access Token for a particular member, any parameters the user doesn't have permission to use are ignored (for example, locked will only be honoured if the authenticated user has permission to lock files).
	 * @reqapiparam	int					category		The ID number of the category the file should be created in
	 * @reqapiparam	int					author			The ID number of the member creating the file (0 for guest). Required for requests made using an API Key or the Client Credentials Grant Type. For requests using an OAuth Access Token for a particular member, that member will always be the author
	 * @reqapiparam	string				title			The file name
	 * @reqapiparam	string				description		The description as HTML (e.g. "<p>This is an file.</p>"). Will be sanatized for requests using an OAuth Access Token for a particular member; will be saved unaltered for requests made using an API Key or the Client Credentials Grant Type.
	 * @apiparam	string				version			The version number
	 * @reqapiparam	object				files			Files. Keys should be filename (e.g. 'file.txt') and values should be file content
	 * @apiparam	object				screenshots		Screenshots. Keys should be filename (e.g. 'screenshot1.png') and values should be file content.
	 * @apiparam	string				prefix			Prefix tag
	 * @apiparam	string				tags			Comma-separated list of tags (do not include prefix)
	 * @apiparam	datetime			date			The date/time that should be used for the file post date. If not provided, will use the current date/time. Ignored for requests using an OAuth Access Token for a particular member.
	 * @apiparam	string				ip_address		The IP address that should be stored for the file. If not provided, will use the IP address from the API request. Ignored for requests using an OAuth Access Token for a particular member.
	 * @apiparam	int					locked			1/0 indicating if the file should be locked
	 * @apiparam	int					hidden			0 = unhidden; 1 = hidden, pending moderator approval; -1 = hidden (as if hidden by a moderator)
	 * @apiparam	int					pinned			1/0 indicating if the file should be featured
	 * @apiparam	int					featured		1/0 indicating if the file should be featured
	 * @apiparam	bool				anonymous		If 1, the item will be posted anonymously.
	 * @throws		1S303/7				NO_CATEGEORY	The category ID does not exist
	 * @throws		1S303/8				NO_AUTHOR		The author ID does not exist
	 * @throws		1S303/9				NO_TITLE		No title was supplied
	 * @throws		1S303/A				NO_DESC			No description was supplied
	 * @throws		1S303/B				NO_FILES		No files were supplied
	 * @throws		2S303/H				NO_PERMISSION	The authorized user does not have permission to create a file in that category
	 * @throws		1S303/I				BAD_FILE_EXT	One of the files has a file type that is not allowed
	 * @throws		1S303/J				BAD_FILE_SIZE	One of the files is too big
	 * @throws		1S303/K				BAD_SS			One of the screenshots is not a valid image
	 * @throws		1S303/L				BAD_SS_SIZE		One of the screenshots is too big by filesize
	 * @throws		1S303/M				BAD_SS_DIMS		One of the screenshots is too big by dimensions
	 * @throws		1S303/N				NO_SS			No screenshots are provided, but screenshots are required for the category
	 * @return		\IPS\downloads\File
	 */
	public function POSTindex()
	{
		/* Get category */
		try
		{
			$category = \IPS\downloads\Category::load( \IPS\Request::i()->category );
		}
		catch ( \OutOfRangeException $e )
		{
			throw new \IPS\Api\Exception( 'NO_CATEGEORY', '1S303/7', 400 );
		}
		
		/* Get author */
		if ( $this->member )
		{
			if ( !$category->can( 'add', $this->member ) )
			{
				throw new \IPS\Api\Exception( 'NO_PERMISSION', '2S303/H', 403 );
			}
			$author = $this->member;
		}
		else
		{
			if ( \IPS\Request::i()->author )
			{
				$author = \IPS\Member::load( \IPS\Request::i()->author );
				if ( !$author->member_id )
				{
					throw new \IPS\Api\Exception( 'NO_AUTHOR', '1S303/8', 400 );
				}
			}
			else
			{
				if ( \IPS\Request::i()->author === 0 ) 
				{
					$author = new \IPS\Member;
					$author->name = \IPS\Request::i()->author_name;
				}
				else 
				{
					throw new \IPS\Api\Exception( 'NO_AUTHOR', '1S303/8', 400 );
				}
			}
		}
		
		/* Check we have a title and a description */
		if ( !\IPS\Request::i()->title )
		{
			throw new \IPS\Api\Exception( 'NO_TITLE', '1S303/9', 400 );
		}
		if ( !\IPS\Request::i()->description )
		{
			throw new \IPS\Api\Exception( 'NO_DESC', '1S303/A', 400 );
		}
		
		/* Validate files */
		if ( !isset( \IPS\Request::i()->files ) or !\is_array( \IPS\Request::i()->files ) or empty( \IPS\Request::i()->files ) )
		{
			throw new \IPS\Api\Exception( 'NO_FILES', '1L296/B', 400 );
		}
		if ( $this->member )
		{
			$this->_validateFilesForMember( $category );
		}
		
		/* Create file record */
		$file = $this->_create( $category, $author );
				
		/* Save records */
		foreach ( array_keys( \IPS\Request::i()->files ) as $name )
		{
			$fileObject = \IPS\File::create( 'downloads_Files', $name, $_POST['files'][ $name ] );
			
			\IPS\Db::i()->insert( 'downloads_files_records', array(
				'record_file_id'	=> $file->id,
				'record_type'		=> 'upload',
				'record_location'	=> (string) $fileObject,
				'record_realname'	=> $fileObject->originalFilename,
				'record_size'		=> $fileObject->filesize(),
				'record_time'		=> time(),
			) );
		}
		if ( $category->bitoptions['allowss'] and isset( \IPS\Request::i()->screenshots ) )
		{
			$primary = 1;
			foreach ( array_keys( \IPS\Request::i()->screenshots ) as $name )
			{
				$fileObject = \IPS\File::create( 'downloads_Screenshots', $name, $_POST['screenshots'][ $name ] );
				
				\IPS\Db::i()->insert( 'downloads_files_records', array(
					'record_file_id'		=> $file->id,
					'record_type'			=> 'ssupload',
					'record_location'		=> (string) $fileObject,
					'record_thumb'			=> (string) $fileObject->thumbnail( 'downloads_Screenshots' ),
					'record_realname'		=> $fileObject->originalFilename,
					'record_size'			=> \strlen( $fileObject->contents() ),
					'record_time'			=> time(),
					'record_no_watermark'	=> NULL,
					'record_default'		=> $primary
				) );
				
				$primary = 0;
			}
		}
		
		/* Recaluclate properties */
		$file = $this->_recalculate( $file );
		
		/* Return */
		$file->save();
		return new \IPS\Api\Response( 201, $file->apiOutput( $this->member ) );
	}

 

Ошибку постоянно получаю эту:

Failed to upload file. Error: {
    "errorCode": "1L296\/B",
    "errorMessage": "NO_FILES"
}

Если вывести \IPS\Request::i()->files вместо 'NO_FILES' выводится последний элемент массива files. Пока не понял логику этого

вы отправляете данные неправильно. API ожидает получить файлы в виде multipart/form-data, а вы отправляете их как обычные данные в запросе.

  • Author
comment_211343
Только что, umbro32111 сказал:

вы отправляете данные неправильно. API ожидает получить файлы в виде multipart/form-data, а вы отправляете их как обычные данные в запросе.

Вы тему прочитайте, там отправляли всеми способами. Ничего не получилось из этого

comment_211355
6 часов назад, MrShandy сказал:

Вы тему прочитайте, там отправляли всеми способами. Ничего не получилось из этого

Для работы необходим multipart/form-data и не как иначе.

Как открыть файл в виде строки для того чтобы передать его в массиве files должен знать ты сам
например на php можно использовать file_get_contents

$communityUrl = 'https://example.ru/';
$apiKey = 'key';
$endpoint = '/downloads/files';

$curl = curl_init( $communityUrl . 'api' . $endpoint );
curl_setopt_array( $curl, array(
  CURLOPT_POST            	=> 1,
  CURLOPT_RETURNTRANSFER	=> TRUE,
  CURLOPT_HTTPAUTH	    	=> CURLAUTH_BASIC,
  CURLOPT_POSTFIELDS      	=> http_build_query( array(
      'category'      => $_POST['category'],
      'author'        => $_POST['author'],
      'title'         => $_POST['title'],
      'description'   => $_POST['description'],
      'files'         => array(
          $_FILES['file']['name'] => file_get_contents( $_FILES['file']['tmp_name'] )
      )
  ) ),
  CURLOPT_USERPWD		    => "{$apiKey}:",
  CURLOPT_USERAGENT			=> "MyUserAgent/1.0"
) );

$response = curl_exec( $curl );

это при условии формы:

<!-- Тип кодирования данных, enctype, требуется указывать только так, как показывает пример -->
<form accept-charset="utf-8" enctype="multipart/form-data" action="https://example.ru/post.php" method="POST">
  <!-- Поле MAX_FILE_SIZE требуется указывать перед полем загрузки файла -->
  <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
  <input type="hidden" name="category" value="1" />
  <input type="hidden" name="author" value="1" />
  <input type="hidden" name="title" value="Test file title" />
  <input type="hidden" name="description" value="Test file description" />
  <!-- Название элемента input определяет название элемента в суперглобальном массиве $_FILES -->
  Отправить файл: <input name="file" type="file" />
  <input type="submit" value="Отправить файл" />
</form>

 

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.


Guest
Ответить в этой теме...

Последние посетители 0

  • No registered users viewing this page.