Sidebar

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

0 votes
132 views
asked May 8 by rich-c-2789 (17,490 points)
edited May 9 by rich-c-2789
Can you show me how to upload an image or binary file using multipart related via a stream?

2 Answers

0 votes

This code snippet demonstrates uploading an image file to a server using multipart/related via an input stream as the content in the qie.callRESTWebService() call.

//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;

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

//The multipart boundary
var boundary = "myBoundary-" + uuid;
//Set the Content-Type to multipart/related and specify the boundary
var requestContentType = "multipart/related; 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.
//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";

//This part header is used to tell the server to treat this as an attachment vs. inline and includes the file name.
//Whether you need to include this header depends on the requirements of the server you’re sending the request to.
openBoundary += "Content-Disposition: attachment; filename=\"dog.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/streamUploadImageFileInMultipartRelated");

// 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 explore why each part of the code is necessary:

Unique Identifiers (UUID):

  • This ensures the filenames and boundaries used are unique for each request. This helps 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) specifies the location of the image file you want to include in the multipart message.
  •  

Multipart Parameters:

  • Boundary: Multipart content consists of multiple parts separated by a boundary. The boundary separates different parts within the multipart message. The receiving server relies on this boundary to identify and process each section or 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 of this part as a JPEG image.
    • Content-Disposition: attachment; filename="dog.jpeg" (Optional) - Informs the server to treat this part as an attachment (optional) and specifies the filename for reference (also optional depending on the server).
  • 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. This frees up resources and avoids leaving unnecessary files on the filesystem.
answered May 8 by rich-c-2789 (17,490 points)
edited May 9 by rich-c-2789
0 votes
answered May 16 by rich-c-2789 (17,490 points)
edited May 16 by rich-c-2789
...