Closed joncameron closed 1 day ago
Need to adjust things on the language support for the API; Language value is set on the model based on default value. We'll need to update that behavior for this purpose, so that the value can be set up front when the supplemental file is created.
Should look at the JSON API standard and other schemas for API architecture.
GET to /supplemental_file/#{id} returns the binary; we don't have a place to get the metadata from one of these routes. GET to /supplemental_file/#{id}.json (with appropriate headers) should get the JSON metadata about the file... and maybe offer a URL to the binary (/supplemental_file/#{id} or /supplemental_file/#{id}/caption etc.). If mirroring for create/update, PUT or POST to .json should be the metadata and PUT or POST to /#{id} should be the binary. For creation, we'd have to figure out what order we want to do this. Submit both things at the same time? What does our model expect or require?
The model has a couple required metadata fields but with Active Storage attachment, you can create the supplemental file object but not have a file attached immediately. We probably wouldn't be able to create the file without any associated metadata. At the very least it would need to be metadata first, file second. Ideally, though, find a way to bundle it all together.
Two relevant options here: https://cloud.google.com/storage/docs/uploading-objects#rest-upload-objects https://www.drupal.org/node/2941420
Ex: POST to /media_objects get the masterfile ID POST to /master_file/id/supplemental_files
When you POST to supplemental_files, it will save or update the media object, OR don't worry about it because it's handled by the handling on the masterfile.
Supplemental file create/update should ensure that saves and index updates are done accordingly as needed.
Note for testing/documentation: When uploading binary content you should provide the mime type in the curl request like in the examples. This attribute should be optional, but I encountered some flaky/weird behavior during development where the SupplementalFile content type was not always being saved properly unless the type=mimetype
attribute was included with the file in the curl request. Required mime types for captions: text/vtt
or text/srt
.
Create with file and metadata:
curl -H "Avalon-Api-Key:abcdef123456" -X POST -F "file=@content_filepath;type=mimetype" -F "metadata=<metadata_filepath" https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files.json
Create with file and inline metadata:
curl -H "Avalon-Api-Key:abcdef123456" -X POST -F "file=@content_filepath;type=mimetype" -F metadata='{"label": "Lunchroom", "language": "French"}' https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files.json
Create with just file:
curl -H "Avalon-Api-Key:abcdef123456" -X POST -F "file=@content_filepath;type=mimetype" https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files.json
Create with just metadata:
curl -H "Avalon-Api-Key:abcdef123456" -X POST -d @metadata_filepath -H "Content-Type:application/json" -H "Accept:application/json" https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files.json
Create with just metadata inline:
curl -H "Avalon-Api-Key:abcdef123456" -X POST '{"label": "Lunchroom", "language": "French"}' -H "Content-Type:application/json" -H "Accept:application/json" https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files.json
Response:
{ "id": :supplemental_file_id }
Update attached file:
curl -H "Avalon-Api-Key:abcdef123456" -X PUT -F "file=@content_filepath;type=mimetype" -H "Accept:application/json" https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files/:id
Response:
{"id": :supplemental_file_id}
curl -H "Avalon-Api-Key:abcdef123456" https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files/:id.json
Response:
{
"id": "131",
"type": "caption",
"label": "Hipparchus (146 to 127 B.C.).vtt",
"language": "English",
"treat_as_transcript": "true",
"machine_generated": "true"
}
Updating metadata requires ALL existing fields except language to be included in the payload. Any existing non-language metadata field that is left out of the payload will be removed.
Update metadata:
curl -H "Avalon-Api-Key:abcdef123456" -X PUT -d @metadata_filepath -H "Content-Type:application/json" -H "Accept:application/json" https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files/:id.json
Payload file:
{
"type": "transcript",
"label": "Hipparchus (146 to 127 B.C.).vtt",
"language": "English",
"treat_as_transcript": false,
"machine_generated": true
}
Update metadata inline:
curl -H "Avalon-Api-Key:abcdef123456" -X PUT -d '{"label": "label", "language": "French"}' -H "Content-Type:application/json" -H "Accept:application/json" https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files/:id.json
Response:
{"id": :supplemental_file_id}
curl -H "Avalon-Api-Key:abcdef123456" "https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files.json"
Returns an array of supplemental files
[
{
"id": "131",
"type": "caption",
"label": "Hipparchus (146 to 127 B.C.).vtt",
"language": "English",
"treat_as_transcript": "true",
"machine_generated": "true"
},
{
"id": "141",
"type "transcript",
"label": "Labelforit.vtt",
"language": "French",
"machine_generated": "true"
}
]
Paginated:
curl -H "Avalon-Api-Key:abcdef123456" "https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files.json?per_page=1&page=2"
Returns array containing per_page results:
[
{
"id": "141",
"type "transcript",
"label": "Labelforit.vtt",
"language": "French",
"machine_generated": "true"
}
]
curl -H "Avalon-Api-Key:abcdef123456" -X DELETE https://avalon-dev.dlib.indiana.edu/master_files/:master_file_id/supplemental_files/:id.json
Deletes a supplemental file from the masterfile
HTTP Response; no JSON returned
@joncameron Can you QA this one since you are most likely to be using this API?
Description
Following from #5710; caption and transcripts should be manipulable via the Avalon API so that these documents can be uploaded and attached to records programatically.
As a user, I want to programmatically add captions, transcripts and supplemental files to master files on a media object.
API
Requirements
For a masterfile:
Upload/attach and set metadata:
Deliberately nice API responses would be nice; that could be an extension past this work
Routes
Questions
does Content Type need to be explicitly added for requests? VTT, DOCX, etc.
Could we do both single request upload and multi-part upload with metadata in json?
Does the request URL need an extra parameter to return JSON? As in /master_files/#{fedora_id}/supplemental_files?format=json. I'm guessing we don't want to clobber the existing responses from the route.
There is already some json handling (not sure what the extent is; may have been autogenerated with scaffolding), so we'll need to make sure existing usage doesn't get changed or is moved to a different route if needed
Request: Add new supplemental file to masterfile
Request: replace existing supplemental file with a new binary file
Request: Get data on supplemental file
GET /master_files/#{fedora_id}//supplemental_files/#{id}.json
Request: Update data on supplemental file
PUT /master_files/#{fedora_id}//supplemental_files/#{id}.json
Request: Get listing of supplemental files on masterfile
GET /master_files/ns064602j/supplemental_files.json Returns an array of supplemental files
Request: Delete supplemental file
DELETE /master_files/#{fedora_id}//supplemental_files/#{id} Deletes a supplemental file from the masterfile
Done Looks Like
QA
Current Caption Upload Example
Current Form Data send on POST