Transferring Files via REST to Store in a Property, Part 1
Tags: rest, iris, intersystems
Published: 2021-06-04 17:33:58

<p style="line-height:1.38"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">A question came up in the InterSystems developer community concerning the possibility of</span></span></span></span></span></span><a href="https://community.intersystems.com/post/twain-interface-cache-application" style="text-decoration:none"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#1155cc"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:underline"><span style="-webkit-text-decoration-skip:none"><span style="text-decoration-skip-ink:none"> creating a TWAIN interface to a Caché application</span></span></span></span></span></span></span></span></a><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">. There were several great suggestions on how to get data from an imaging device on a web client to a server, then store this data in a database.&nbsp;</span></span></span></span></span></span></p>

<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">However, in order to implement any of these suggestions, you need to be able to transfer data from a web client to a database server and store the received data in a class property (or a table cell, as was the case in the question). This technique can be useful not only for transferring imaging data received from a TWAIN device, but also for other tasks such as organizing a file archive, an image share, and so forth.&nbsp;</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Thus, the main objective of this article is to show how to write a RESTful service to get data from the body of an HTTP POST command either in a raw state or wrapped in a JSON structure.</span></span></span></span></span></span></p>
<h1 style="line-height:1.38; margin-top:27px; margin-bottom:8px"><span style="font-size:20pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">REST Basics</span></span></span></span></span></span></h1>
<p style="line-height:1.38"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Before getting to the specifics, let’s start with a few words about REST in general and how RESTful services are created in IRIS.</span></span></span></span></span></span></p>

<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Representational state transfer (REST) is an architectural style for distributed hypermedia systems. The key abstraction of information in REST is a resource which has its proper identifier and can be represented in a JSON, XML, or other format known to both server and client.&nbsp;</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Usually, HTTP is used to transfer data between client and server. Each CRUD (create, read, update, delete) operation has its own HTTP method (POST, GET, PUT, DELETE), while each resource or collection of resources has its own URI.</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">In this article, I’ll be using only the POST method to insert a new value into the database, so I need to know its constraints.&nbsp;</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">POST doesn’t have any limit on the size of data stored in its body according to the </span></span></span></span></span></span><a href="https://tools.ietf.org/html/rfc7231#section-4.3.3" style="text-decoration:none"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#1155cc"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:underline"><span style="-webkit-text-decoration-skip:none"><span style="text-decoration-skip-ink:none">IETF RFC7231 4.3.3 Post</span></span></span></span></span></span></span></span></a><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> specification. But different web servers and browsers impose their own limits, typically from 1MB to 2GB. For example, </span></span></span></span></span></span><a href="https://httpd.apache.org/docs/2.4/mod/core.html#limitrequestbody" style="text-decoration:none"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#1155cc"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:underline"><span style="-webkit-text-decoration-skip:none"><span style="text-decoration-skip-ink:none">Apache</span></span></span></span></span></span></span></span></a><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> allows a maximum of 2GB. In any case, if you need to send a 2GB file, you might want to rethink your approach.</span></span></span></span></span></span></p>
<h1 style="line-height:1.38; margin-top:27px; margin-bottom:8px"><span style="font-size:20pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Requirements for a RESTful Service in IRS</span></span></span></span></span></span></h1>
<p style="line-height:1.38"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">In IRIS, in order to implement a RESTful service, you have to:</span></span></span></span></span></span></p>

<ul>
<li aria-level="1" style="list-style-type:disc"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Create a class broker that extends the abstract class </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">%CSP.REST</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">. This, in turn, extends </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">%CSP.Page</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">, and this makes it possible to access different useful methods, parameters, and objects, in particular </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">%request</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">).</span></span></span></span></span></span></li>
<li aria-level="1" style="list-style-type:disc"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Specify </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">UrlMap</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> to define routes.</span></span></span></span></span></span></li>
<li aria-level="1" style="list-style-type:disc"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Optionally set the </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">UseSession</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> parameter to specify whether each REST call is executed in its own web session or shares a single session with other REST calls.</span></span></span></span></span></span></li>
<li aria-level="1" style="list-style-type:disc"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Provide class methods to perform operations defined in routes.</span></span></span></span></span></span></li>
<li aria-level="1" style="list-style-type:disc"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Define the CSP web application and specify its security on the web application page (System Administration &gt; Security &gt; Applications &gt; Web Applications), where the </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Dispatch</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> class should hold the name of the user class and </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Name</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">, the first part of the URL for the REST call.</span></span></span></span></span></span></li>
</ul>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">In general, there are several ways to send big chunks of data (files) and their metadata from client to server, such as:</span></span></span></span></span></span></p>
<ul>
<li aria-level="1" style="list-style-type:disc"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Base64-encode the file and the metadata and add processing overhead to both the server and the client for encoding/decoding.</span></span></span></span></span></span></li>
<li aria-level="1" style="list-style-type:disc"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Send the file first and return an ID to the client, which then sends the metadata with the ID. The server reassociates the file and the metadata.</span></span></span></span></span></span></li>
<li aria-level="1" style="list-style-type:disc"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Send the metadata first and return an ID to the client, which then sends the file with the ID, and the server reassociates the file and the metadata.</span></span></span></span></span></span></li>
</ul>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">In this first article, I’m going to basically take the second approach, but without returning ID to the client and adding the metadata (the filename to store as another property) because there’s nothing exceptional about this task. In a second article, I’ll use the first approach, but I’ll package my file and metadata (the filename) in a JSON structure before sending it to the server.</span></span></span></span></span></span></p>
<h1 style="line-height:1.38; margin-top:27px; margin-bottom:8px"><span style="font-size:20pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Implementing the RESTFul Service</span></span></span></span></span></span></h1>
<p style="line-height:1.38"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Now let’s get to the specifics. First, let’s define the class, properties of which we’ll be setting</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">:</span></span></span></span></span></span></p>

<pre><code>Class RestTransfer.FileDesc Extends %Persistent
{
&nbsp;&nbsp;Property File As %Stream.GlobalBinary;
&nbsp;&nbsp;Property Name As %String;
}</code></pre>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Of course, you’ll usually have more metadata to go with the file, but this should suffice for our purposes.</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Next, we need to create a class broker, which we’ll expand later with routes and methods:</span></span></span></span></span></span></p>
<pre><code>Class RestTransfer.Broker Extends %CSP.REST
{
&nbsp;&nbsp;XData UrlMap
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&lt;Routes&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Routes&gt;
&nbsp;&nbsp;}
}</code></pre>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">And lastly, for the preliminary setup we need to specify this application in a list of web applications:</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"><span style="border:none"><span style="display:inline-block"><span style="overflow:hidden"><span style="width:468px"><span style="height:252px"><img src="https://lh4.googleusercontent.com/lkjPLUflbNHXgMKtwm0_pddObiF6-Azydo0NzMbdO3c1WjqPLrL77ek5AS_uGQDM4ugWFQXHS6hJNN5FEEUNP3SI8ERKa5ALdGbwRlbuWBU8taf262ldtPM-wyoFQViNTJiyAEiH"></span></span></span></span></span></span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Now that the preliminary setup is done, we can write methods to save a file received from a REST client (I’ll use the </span></span></span></span></span></span><a href="https://install.advancedrestclient.com/install" style="text-decoration:none"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#1155cc"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:underline"><span style="-webkit-text-decoration-skip:none"><span style="text-decoration-skip-ink:none">Advanced REST Client</span></span></span></span></span></span></span></span></a><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">) into a database as a </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">File</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> property of an instance of class </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">RestTransfer.FileDesc</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">.</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">We’ll start by working with information stored as raw data in the body of POST method. First, let’s add a new route to </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">UrlMap</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">:</span></span></span></span></span></span></p>
<p><codepre><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">&lt;Route Url="/file" Method="POST" Call="InsertFileContents"/&gt;</span></span></span></span></span></span></codepre></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">This route specifies that when the service receives a POST command with URL </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">/RestTransfer/file</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">, it should call the </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">InsertFileContents</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> class method. To make things easier, inside this method I’ll create a new instance of a class </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">RestTransfer.FileDesc</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> and set its </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">File</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> property to the received data. This returns the status and a JSON-formatted message indicating either success or error. Here’s the class method:</span></span></span></span></span></span></p>
<pre><code>ClassMethod InsertFileContents() As %Status
{
&nbsp;&nbsp;Set result={}
&nbsp;&nbsp;Set st=0&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;set f = ##class(RestTransfer.FileDesc).%New()
&nbsp;&nbsp;if (f = $$$NULLOREF) {
&nbsp;&nbsp;&nbsp;&nbsp;do result.%Set("Message","Couldn't create an instance of the class")
&nbsp;&nbsp;} else {
&nbsp;&nbsp;&nbsp;&nbsp;set st = f.File.CopyFrom(%request.Content)
&nbsp;&nbsp;&nbsp;&nbsp;If $$$ISOK(st) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set st = f.%Save()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If $$$ISOK(st) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do result.%Set("Status","OK")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do result.%Set("Message",$system.Status.GetOneErrorText(st))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;} else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do result.%Set("Message",$system.Status.GetOneErrorText(st))
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;}
&nbsp;&nbsp;write result.%ToJSON()
&nbsp;&nbsp;Quit st
}</code></pre>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">First, it creates a new instance of class </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">RestTransfer.FileDesc</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> and checks that it was created successfully and we have an OREF. If the object couldn’t be created, we form a JSON structure:&nbsp;</span></span></span></span></span></span></p>
<p><codepre><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">{"Message", "Couldn't create an instance of class"}</span></span></span></span></span></span></codepre></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">If the object was created, the contents of the request are copied into the property </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">File</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">. If copying was not successful, we form a JSON structure with a description of the error:&nbsp;</span></span></span></span></span></span></p>
<p><codepre><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">{"Message",$system.Status.GetOneErrorText(st)}</span></span></span></span></span></span></codepre></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">If the contents were copied, we save the object, and if the save is successful, we form a JSON </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">{"Status","OK"}</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">. If not, the JSON returns an error description.&nbsp;</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Finally, we write the JSON to a response and return status </span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:'Courier New'"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">st</span></span></span></span></span></span><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">.</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Here’s an example of transferring an image:</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"><span style="border:none"><span style="display:inline-block"><span style="overflow:hidden"><span style="width:468px"><span style="height:322px"><img height="322" src="https://lh6.googleusercontent.com/JoWOHcPK5liAhznh61zUvlFY66J7Q8TUsLdoea94UEeqSHE1rSnt9jtNbZMLDbn3bv-mQBYjmVEdUkuqKqM2eS3UHq0SkQD8PCNvEWw47H9XTzcHj0s1tIOtsbaF31nSRo4cEt1J" width="468"></span></span></span></span></span></span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">How it’s saved in the database:</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"><span style="border:none"><span style="display:inline-block"><span style="overflow:hidden"><span style="width:308px"><span style="height:58px"><img height="58" src="https://lh6.googleusercontent.com/SYKHRNrVqBq2O0Mefo5jPrncgU0XAMClnjQQNSPrw-228FG0RiCeCii3HQcwGIabKXMIkP9hPLyK1yD8hhxzE-4nQap2gwwNyOtS1hQec7nYZOoZ5pSDmF4Edju7vSIrBjDrkENz" width="308"></span></span></span></span></span></span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">We can save this stream to a file and see that it was transferred without change:</span></span></span></span></span></span></p>
<pre><code>set f = ##class(RestTransfer.FileDesc).%OpenId(4)
set s = ##class(%Stream.FileBinary).%New()
set s.Filename = "D:\Downloads\test1.jpg"
do s.CopyFromAndSave(f.File)</code></pre>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">The same can be done with a text file:</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"><span style="border:none"><span style="display:inline-block"><span style="overflow:hidden"><span style="width:468px"><span style="height:322px"><img height="322" src="https://lh4.googleusercontent.com/9oH_0YOanIT9Rz2PF6ijXJBWB2PTaCIjuhcVY26v2OwwM8bxYayESfTKCuXgBTvcY7u47W24arTp0BXHRUTeboSApbfaTPQM3HvjrfyiTPyLC5oBjm_Mp5-wQYHeHmBtXXLjOLEM" width="468"></span></span></span></span></span></span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">This will also be visible in globals:</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"><span style="border:none"><span style="display:inline-block"><span style="overflow:hidden"><span style="width:468px"><span style="height:30px"><img height="30" src="https://lh5.googleusercontent.com/nEugr5ONsH88ycJsfKKx13df2G1D953YldIqmzRmRVqWn4DDSTJmP6OhE8DpeRs7gBflBML-jLqfKYkH8GQ-aGjT1RcgpWqnKtV13uXb0_nXJbmMXtdZpzlZYyotOsFg6nLvE6TE" width="468"></span></span></span></span></span></span></span></span></span></span> </span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">And we can store executables or any other type of data:</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"><span style="border:none"><span style="display:inline-block"><span style="overflow:hidden"><span style="width:468px"><span style="height:322px"><img height="322" src="https://lh4.googleusercontent.com/etYBQ99ftbiRAtktOSdOP2-0dhq6afA03nQX-SEaDoUEmEOgOi6fJ1kunnG0MfFcatYw5Ak5BtFxVobdLXgTn9wXXe3QoGSO5nYFMY1js4nBcV1CpSAMh6l9d7rgvJ1Qa73zKiRs" width="468"></span></span></span></span></span></span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">We can check the size in globals, and it’s correct:</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"><span style="border:none"><span style="display:inline-block"><span style="overflow:hidden"><span style="width:457px"><span style="height:107px"><img height="107" src="https://lh4.googleusercontent.com/G7ykwnx6_J0s8lgGvBwsJtYgQIqYDbuzixUPeel90LWmefvEGMr18qYTVV-ArvnVthFRtNSvRaFKSG-_U6gX2DSzwSYYZv1Zy0aUvTZ0zdCE5QkADgr7rlFJcLeGMB67UsMc9kLS" width="457"></span></span></span></span></span></span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">Now that this part works as it should, let’s take a look at the second approach — getting the contents of the file and its metadata (the filename) stored in JSON format and transferred in the body of a POST method.&nbsp;</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">You can read more about creating REST services in the InterSystems</span></span></span></span></span></span><a href="https://docs.intersystems.com/iris20191/csp/docbook/Doc.View.cls?KEY=GREST" style="text-decoration:none"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#1155cc"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:underline"><span style="-webkit-text-decoration-skip:none"><span style="text-decoration-skip-ink:none"> documentation</span></span></span></span></span></span></span></span></a><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">.&nbsp;</span></span></span></span></span></span></p>
<p><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">The example code for the both approaches is on </span></span></span></span></span></span><a href="https://github.com/Gra-ach/RESTFileTransfer" style="text-decoration:none"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#1155cc"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:underline"><span style="-webkit-text-decoration-skip:none"><span style="text-decoration-skip-ink:none">GitHub</span></span></span></span></span></span></span></span></a><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none"> and </span></span></span></span></span></span><a href="https://openexchange.intersystems.com/package/RESTFileTransfer" style="text-decoration:none"><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#1155cc"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:underline"><span style="-webkit-text-decoration-skip:none"><span style="text-decoration-skip-ink:none">InterSystems Open Exchange</span></span></span></span></span></span></span></span></a><span style="font-size:11pt; font-variant:normal; white-space:pre-wrap"><span style="font-family:Arial"><span style="color:#000000"><span style="font-weight:400"><span style="font-style:normal"><span style="text-decoration:none">. If you have any questions or suggestions pertaining to either, please don’t hesitate to write them in the comments section.</span></span></span></span></span></span></p>