Sidebar

Uploading a Image/Binary File via Stream with qie.callRESTWebService() as multipart/form-data request.

0 votes
617 views
asked May 9 by rich-c-2789 (17,610 points)
Can you show me how to upload an image or binary file using multipart/form-data via a stream?

2 Answers

0 votes

This demonstrates uploading an image using multipart/form-data via an input stream passed to qie.callRESTWebService().

//Get an uuid to make the boundary and file names unique.
var uuid = qie.getUUID();
//Create a temporary file for the multipart content.
var multipartFileName = "request_" + uuid + ".tmp";
var multipartFilePath = "/tmp/" + multipartFileName;

//The image to add to the content
var imageName = "dog.jpeg";
var imagePath = "/Users/dir/Pictures/" + imageName;

//The name of the multipart boundary
var boundary = "myBoundary-" + uuid;
//Set the Content-Type to multipart/form-data and specify the boundary
var requestContentType = "multipart/form-data; boundary=" + boundary;

// Create a new parameter map. This would be used to add headers to the request.
var parameterMap = qie.newParameterMap();
// For this exaple no headers are needed. If required they would be added with the "http.header." prefix. Example:
// parameterMap.put("http.header.headerName", "value");

//Build the content without looading all the bytes into memory.
var outputStream = new java.io.FileOutputStream(multipartFilePath);

// Write begining of first boundary.
// NOTE: must start with two dashses and end with a new line "\r\n"
var openBoundary = "--" + boundary + "\r\n";

//Add headers for the part.  NOTE: we do NOT need the "http.header." prefix when adding headers to a part.
//This is added to indicate to the server the form field (favoriteAnimal) and the filename being uploaded (dog.jpeg)
openBoundary += "Content-Disposition: form-data; name=\"favoriteAnimal\"; filename=\"" + imageName + "\"\r\n";
//Since this example uses a stream vs. a string, this header is not needed.
//openBoundary += "encoding: ISO-8859-1\r\n";
//The server used for this example is a QIE HTTP Listener.  Which handles multipart content with a boundary when streaming. However, other servers may require it.
//openBoundary += "content-transfer-encoding: binary\r\n";
openBoundary += "Content-Type: image/jpeg\r\n";

//Write the openBoundary to the output stream.
outputStream.write((new java.lang.String(openBoundary)).getBytes());

//Add a blank line before we write the image data to the part.
outputStream.write((new java.lang.String("\r\n")).getBytes());

//Stream the image to the outputStream
var inputStream = new java.io.FileInputStream(imagePath);
// The size of a chunk to copy at a time.
var chunkSize = 1024;
//Creates a new byte[] to store a chunk in.
var chunkByteArray = new Packages.java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, chunkSize);
//This is the number of bytes read by calling inputStream.read.
//Used to tell when there are no more bytes to read.
var bytesRead;
while ((bytesRead = inputStream.read(chunkByteArray)) != -1) {
   //Write the chunk to the outputStream.
   outputStream.write(chunkByteArray, 0, bytesRead);
}

//Close image boundary
var closeBoundary = "\r\n--" + boundary + "--\r\n";
outputStream.write((new java.lang.String(closeBoundary)).getBytes());

//Close the input and output streams
inputStream.close();
outputStream.flush();
outputStream.close();

// Open the multipart file (saved above) as a stream.
var contentInputStream = java.io.FileInputStream(multipartFilePath);

//URL template for the endpoint. This is used to override the endpoint in the web service connection.
var urlTemplate = qie.evaluateTemplate("http://localhost:8083/streamUploadImageFileInMultipartFormData");

//Call a REST web service using the provided parameters
var result = qie.callRESTWebService(
"wsName",
urlTemplate,
"POST",
contentInputStream,
requestContentType,
parameterMap,
60000);

//Cache the response for further processing later.
messageCache.setValue("restResult", result);

//Delete the temporary file
qie.deleteFile(multipartFilePath);

let's take a closer look:

Unique Identifiers (UUID):

  • This ensures the filenames and boundaries are unique. To avoid potential conflicts or overwrites when handling multiple requests.
  •  

File Paths:

  • The temporary file path (multipartFilePath) stores the constructed multipart message before uploading. It acts as a staging area for the message before sending it.
  • The image path (imagePath) is the location of the image file to include in the multipart message.
  •  

Multipart Parameters:

  • Boundary: Multipart content consists of multiple parts separated by a boundary. The receiving server relies on this boundary to identify and process each part (only one part containg image data in this case).  Setting a unique boundary ensures proper delineation between parts.
  • Content-Type: Informs the server that the message body is multipart and specifies the boundary string used for separation.
  •  

Building Multipart Content:

  • Temporary File: This file holds the constructed multipart message with the image data before sending it as a whole.
  • Opening Boundary: Signals the beginning of a part within the multipart message. The specific format with double dashes and a newline is essential for the server to recognize it.
  • Image Part Headers:
    • Content-Type: image/jpeg - Identifies the content as a JPEG image.
    • Content-Disposition: form-data; name="petField" filename="dog.jpeg" (Required) - Provides additional metadata about the content being transmitted (form field and filename)
  • Writing Image Data: Reads the image file in chunks for efficiency and writes it to the temporary file containing the multipart message.
  • Closing Boundary: Signals the end of the image part within the multipart message. The format again follows a specific pattern for proper recognition by the server.
  •  

Uploading Multipart Message:

  • Opening Multipart File Stream: The temporary file with the complete multipart message is opened as a stream for efficient transmission. This avoids loading the entire content into memory at once.
  • Web Service URL Template: Defines the endpoint where the web service expects to receive the multipart upload.
  • Uploading the Stream: The content stream (contentInputStream) containing the multipart message is sent to the web service using a POST request (common for uploads). 
  • Storing the Response: Caching the response can be helpful if the response needs to be accessed multiple times in a later mapping funnction or mapping node.
  •  

Cleanup:

  • Deleting Temporary File: Once the upload is complete, the temporary file is no longer needed. 
answered May 9 by rich-c-2789 (17,610 points)
edited May 16 by rich-c-2789
0 votes
answered May 16 by rich-c-2789 (17,610 points)
edited May 16 by rich-c-2789
...