Загрузка файла PDF в набор данных CKAN из-за сбоя ресурса с {file} не может быть сериализована json

Мой простой скрипт на Python для создания набора данных и добавления в этот набор данных одного файла PDF, так как ресурс не работает с {file}, не сериализуем json.

# coding=utf-8
# import base64
import ckanapi
import requests
import csv
import json
import pprint
import socket
import netifaces as ni

# UPDATE THESE AND ONLY THESE.
api_token = '***'
the_hostname = socket.gethostname()
the_ipaddress = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
site_url = 'http://' + the_ipaddress + ':5000'

endpoint_p = '{}/api/3/action/package_create'.format(site_url)
endpoint_r = '{}/api/3/action/resource_create'.format(site_url)
headers = {'Authorization': api_token}

payload_p = {
    "name": "test01",
    "private": "true",
    "state": "active",
    "owner_org": "b15a6f45-e2ed-4587-8c5e-a92dbc9f157d",
    "maintainer" : "Forms Management",
    "maintainer_email" : "[email protected]",
    "author" : "Test Author",
    "author_email" : "[email protected]"
}

payload_r = {
    "package_id": "null",
    "name": "English - test01 - Test Description",
    "url": "upload",
    "upload": open('/var/www/upload/2nd/unzipped/002-33-5098E/33-5098E.pdf', 'r'),
    "description": "This is a test resource attached to dataset test01",
    "notes": "This is a longer block of text that is for the resource test01e which is attached to the dataset test01"
}
      
filepaths = {
    "thepath": "/var/www/upload/2nd/unzipped/002-33-5098E/33-5098E.pdf"
}
        
req_p = requests.post(endpoint_p, json=payload_p, headers=headers)

theLastResponse = req_p.json()

theLastPackageCreated = theLastResponse['result']['id']

payload_r["package_id"] = theLastPackageCreated

req_r = requests.post(endpoint_r, json = payload_r, headers = headers) # resource_create()

Это выдает ошибку {файл} не сериализуем в json. Файл представляет собой PDF, который является двоичным файлом, но я не уверен, требуется ли какой-либо тип кодирования (обратите внимание на закомментированный модуль base64... Я не хотел идти по этому пути, не спросив, является ли это правильный подход)

Документация по CKAN API здесь: https://docs.ckan.org/en/2.9/api/#ckan.logic.action.create.resource_create

говорит, что загрузка должна быть (FieldStorage (необязательно) требует multipart/form-data) – (необязательно), но все примеры сценариев, которые я видел для загрузки файлов в CKAN, показывают только код и именно то, что я сделал здесь, никакой дополнительной предварительной обработки загружаемого файла или чего-то еще, поэтому я не уверен, в чем именно может быть проблема... пожалуйста, помогите, если можете!


person Ryan Germann    schedule 25.09.2020    source источник


Ответы (1)


Я скопировал ваш код и запустил модифицированную версию с локальной копией CKAN для разработчиков, и она работала без проблем ПОСЛЕ моих модов, которые включены ниже.

В частности:

  • payload_r -> Все эти дополнительные вещи не нужны, но вы можете включить другие метаданные ресурса, такие как описание, имя и т. д., если хотите, просто
  • req_r -> 1) передать полезную нагрузку здесь как data вместо json, так как это multipart-form-data. 2) пришлите сюда файл с параметром files.

Документы: https://docs.ckan.org/en/2.9/maintaining/filestore.html#filestore-api

IMO, это не столько проблема CKAN, сколько понимание выбранной библиотеки (т.е. запросов). есть много способов сделать это с помощью различных инструментов.

Мне также пришлось обновить полезные нагрузки, чтобы они соответствовали моей схеме, но если предположить, что это правильно для вас, это должно работать.

# coding=utf-8
# import base64
import ckanapi
import requests
import csv
import json
import pprint
import socket
import netifaces as ni

# UPDATE THESE AND ONLY THESE.
api_token = '***'
the_hostname = socket.gethostname()
the_ipaddress = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
site_url = 'http://' + the_ipaddress + ':5000'

endpoint_p = '{}/api/3/action/package_create'.format(site_url)
endpoint_r = '{}/api/3/action/resource_create'.format(site_url)
headers = {'Authorization': api_token}

payload_p = {
    "name": "test01",
    "private": "true",
    "state": "active",
    "owner_org": "b15a6f45-e2ed-4587-8c5e-a92dbc9f157d",
    "maintainer" : "Forms Management",
    "maintainer_email" : "[email protected]",
    "author" : "Test Author",
    "author_email" : "[email protected]"
}

payload_r = {
    "package_id": "null"
}
      
filepaths = {
    "thepath": "/var/www/upload/2nd/unzipped/002-33-5098E/33-5098E.pdf"
}
        
req_p = requests.post(endpoint_p, json=payload_p, headers=headers)

theLastResponse = req_p.json()

theLastPackageCreated = theLastResponse['result']['id']

payload_r["package_id"] = theLastPackageCreated

req_r = requests.post(endpoint_r, data=payload_r, headers=headers, files=[('upload', file('/var/www/upload/2nd/unzipped/002-33-5098E/33-5098E.pdf'))]) # resource_create()
person user3366016    schedule 25.09.2020
comment
Большое спасибо, это исправлено. Теперь я могу реинтегрировать биты, которые считывают метаданные и пути к файлам из .CSV. Вы сделали мой день! - person Ryan Germann; 25.09.2020