Replies: 3 comments 19 replies
-
More detailed notes and examples for review. Media Upload using Pre-signed URLsThis is a proposed solution to media upload. Data RepresentationData StructureThese are the required fields to represent the upload process for media <EntityType Name="Media">
<Property Name="PresignedUrl" Type="Edm.String" />
<Property Name="PresignedUrlExpiry" Type="Edm.DateTimeOffset" />
<Property Name="MediaStatus" Type="Edm.String" />
<Property Name="MediaStatusDescription" Type="Edm.String" />
</EntityType> Status of the MediaThe status of the media will be tracked on the
Some examples of
Media Upload Process - Happy PathThe creation of the media resource will be done using as a standard Odate Update Process. (Defined in RCP-10). The post should included all known metadata about the media with the exception of only the media byte stream. If the media is a reference to external URL reference, the server should ingest the Create Media ResourceCreate the initial media record using the Data standard. This could be an expanded record on another resource a secondary approach but the example will be with REQUEST POST https://api.my-webapi.io/Media
OData-Version: 4.01
Content-Type: application/json
Accept: application/json
Prefer: return=representation {
"Caption": "Ipsum Lorum",
"Order": 1,
"ImageType": "image/jpeg",
} RESPONSE HTTP/2 201 Created
OData-Version: 4.01
EntityId: "12345"
Location: https://api.my-webapi.io/Media('12345')
Content-Length: 200
Content-Type: application/json
Preference-Applied: return=representation {
"@OData.context":"https://api.my-webapi.io/$metadata#Media/$entity",
"@OData.id":"https://api.my-webapi.io/Media('12345')",
"@OData.editLink":"https://api.webapi.io/Media('12345')",
"@OData.etag": "W/\"aBcDeFgHiJkLmNoPqRsTuVwXyz\"",
"MediaObjectID": "12345",
"Caption": "Ipsum Lorum",
"Order": 1,
"ImageType": "image/jpeg",
"MediaStatus": "Incomplete",
"MediaStatusDescription": "Awaiting Byte Stream",
"PresignedUrl": "https://storage.my-webapi.io/media/12345.jpg?authentication_token=my-one-time-use-auth-token-12345-zyxwut",
"PresignedUrlExpiry": "2023-08-01T13:00:00+00:00",
} The return from the POST will return a pre-signed URL with an validity window for that URL. Upload the Media byte arrayThie bytestrem upload will be a simple HTTP POST transaction to the provided to the endpoint with no other required data. No external fields, headers or payloads are required to post the media stream. All requirements for the POST must be part of the REQUEST
RESPONSE
Media post processingThe original media record will transition to If any processing fails, the media record will be have a status of Rules can be written against the Successful Media UploadThe media record can up queries to confirm the media has successfully been processed. REQUEST POST https://api.my-webapi.io/Media('12345')
OData-Version: 4.01
Content-Type: application/json
Accept: application/json
Prefer: return=representation RESPONSE HTTP/2 200
OData-Version: 4.01
EntityId: "12345"
Location: https://api.my-webapi.io/Media('12345')
Content-Length: 200
Content-Type: application/json
Preference-Applied: return=representation {
"@OData.context":"https://api.my-webapi.io/$metadata#Media/$entity",
"@OData.id":"https://api.my-webapi.io/Media('12345')",
"@OData.editLink":"https://api.webapi.io/Media('12345')",
"@OData.etag": "W/\"aBcDeFgHiJkLmNoPqRsTuVwXyz\"",
"MediaObjectID": "12345",
"Caption": "Ipsum Lorum",
"Order": 1,
"ImageType": "image/jpeg",
"MediaStatus": "Complete",
"MediaStatusDescription": "Processing Complete",
"PresignedUrl": null,
"PresignedUrlExpiry": null,
} Media Upload Process error statesThese are the cases where the media record will not reach the Media Record created but no byte stream providedThis will leave the media record in a REQUEST POST https://api.my-webapi.io/Media('12345')
OData-Version: 4.01
Content-Type: application/json
Accept: application/json
Prefer: return=representation RESPONSE HTTP/2 200
OData-Version: 4.01
EntityId: "12345"
Location: https://api.my-webapi.io/Media('12345')
Content-Length: 200
Content-Type: application/json
Preference-Applied: return=representation {
"@OData.context":"https://api.my-webapi.io/$metadata#Media/$entity",
"@OData.id":"https://api.my-webapi.io/Media('12345')",
"@OData.editLink":"https://api.webapi.io/Media('12345')",
"@OData.etag": "W/\"aBcDeFgHiJkLmNoPqRsTuVwXyz\"",
"MediaObjectID": "12345",
"Caption": "Ipsum Lorum",
"Order": 1,
"ImageType": "image/jpeg",
"MediaStatus": "Incomplete",
"MediaStatusDescription": "Awaiting Byte Stream",
"PresignedUrl": "https://storage.my-webapi.io/media/12345.jpg?authentication_token=my-one-time-use-auth-token-12345-zyxwut",
"PresignedUrlExpiry": "2023-08-01T13:00:00+00:00",
} PresignedUrl ExpiresIf a Refreshed CaseREQUEST POST https://api.my-webapi.io/Media('12345')
OData-Version: 4.01
Content-Type: application/json
Accept: application/json
Prefer: return=representation RESPONSE HTTP/2 200
OData-Version: 4.01
EntityId: "12345"
Location: https://api.my-webapi.io/Media('12345')
Content-Length: 200
Content-Type: application/json
Preference-Applied: return=representation {
"@OData.context":"https://api.my-webapi.io/$metadata#Media/$entity",
"@OData.id":"https://api.my-webapi.io/Media('12345')",
"@OData.editLink":"https://api.webapi.io/Media('12345')",
"@OData.etag": "W/\"aBcDeFgHiJkLmNoPqRsTuVwXyz\"",
"MediaObjectID": "12345",
"Caption": "Ipsum Lorum",
"Order": 1,
"ImageType": "image/jpeg",
"MediaStatus": "Incomplete",
"MediaStatusDescription": "Awaiting Byte Stream",
"PresignedUrl": "https://storage.my-webapi.io/media/12345.jpg?authentication_token=my-one-time-use-auth-token-12345-abcdefg",
"PresignedUrlExpiry": "2023-09-01T14:00:00+00:00",
} Rejected CaseREQUEST POST https://api.my-webapi.io/Media('12345')
OData-Version: 4.01
Content-Type: application/json
Accept: application/json
Prefer: return=representation RESPONSE HTTP/2 200
OData-Version: 4.01
EntityId: "12345"
Location: https://api.my-webapi.io/Media('12345')
Content-Length: 200
Content-Type: application/json
Preference-Applied: return=representation {
"@OData.context":"https://api.my-webapi.io/$metadata#Media/$entity",
"@OData.id":"https://api.my-webapi.io/Media('12345')",
"@OData.editLink":"https://api.webapi.io/Media('12345')",
"@OData.etag": "W/\"aBcDeFgHiJkLmNoPqRsTuVwXyz\"",
"MediaObjectID": "12345",
"Caption": "Ipsum Lorum",
"Order": 1,
"ImageType": "image/jpeg",
"MediaStatus": "Rejected",
"MediaStatusDescription": "Media record has timed out",
"PresignedUrl": null,
"PresignedUrlExpiry": null,
} Media uploaded but byte stream rejectedIf the media is rejected, the vendor can eithe allow for the record update by providing the Resubmit CaseREQUEST POST https://api.my-webapi.io/Media('12345')
OData-Version: 4.01
Content-Type: application/json
Accept: application/json
Prefer: return=representation RESPONSE HTTP/2 200
OData-Version: 4.01
EntityId: "12345"
Location: https://api.my-webapi.io/Media('12345')
Content-Length: 200
Content-Type: application/json
Preference-Applied: return=representation {
"@OData.context":"https://api.my-webapi.io/$metadata#Media/$entity",
"@OData.id":"https://api.my-webapi.io/Media('12345')",
"@OData.editLink":"https://api.webapi.io/Media('12345')",
"@OData.etag": "W/\"aBcDeFgHiJkLmNoPqRsTuVwXyz\"",
"MediaObjectID": "12345",
"Caption": "Ipsum Lorum",
"Order": 1,
"ImageType": "image/jpeg",
"MediaStatus": "Rejected",
"MediaStatusDescription": "Byte stream is not of type image/jpeg",
"PresignedUrl": "https://storage.my-webapi.io/media/12345-attempt2.jpg?authentication_token=my-one-time-use-auth-token-12345-abcdefg",
"PresignedUrlExpiry": "2023-09-01T14:00:00+00:00",
} Write-Once CaseREQUEST POST https://api.my-webapi.io/Media('12345')
OData-Version: 4.01
Content-Type: application/json
Accept: application/json
Prefer: return=representation RESPONSE HTTP/2 200
OData-Version: 4.01
EntityId: "12345"
Location: https://api.my-webapi.io/Media('12345')
Content-Length: 200
Content-Type: application/json
Preference-Applied: return=representation {
"@OData.context":"https://api.my-webapi.io/$metadata#Media/$entity",
"@OData.id":"https://api.my-webapi.io/Media('12345')",
"@OData.editLink":"https://api.webapi.io/Media('12345')",
"@OData.etag": "W/\"aBcDeFgHiJkLmNoPqRsTuVwXyz\"",
"MediaObjectID": "12345",
"Caption": "Ipsum Lorum",
"Order": 1,
"ImageType": "image/jpeg",
"MediaStatus": "Rejected",
"MediaStatusDescription": "Byte stream is not of type image/jpeg",
"PresignedUrl": null,
"PresignedUrlExpiry": null,
} |
Beta Was this translation helpful? Give feedback.
-
Thanks for putting this together. I think we should talk about some of this a bit. |
Beta Was this translation helpful? Give feedback.
-
This discussion should be closed and the discussion should move to #116 which is the new OData version of the proposal. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Step 1
Post data to Media resource with all the metadata available for the image prior to uploading the base64 encoded image data.
Note: In this step there are two cases ... either the record that the Media is attached to is included in the initial creation of the Media metadata (ResourceName, ResourceRecordKey), or it isn't. If not, then that information needs to be provided at some point (after step 2).
Step 2
Once the Media record has been created, the client can upload the binary image data by obtaining the pre-signed URL attached to the Media item that was created. The pre-signed URLs will be generated as a result of step (1), and will have an expiration timestamp associated with them.
Media Statuses
We also need to define statuses in the Media Resource to reflect the various stages of processing.
If the record has been rejected for some reason, either processing failed or there was a compliance issue (for example), there will also be a StatusDescription to let clients know what failed.
Beta Was this translation helpful? Give feedback.
All reactions