In this demo, we will show you how to customize Web Chat to directly upload file(s) to Azure Storage, and then send the blob URL to the bot for validation and further processing.
Direct Line provides a temporary storage of user attachments, up to 4 MB per attachment for about 24 hours. If the end-user needs to upload more than 4 MB, it is always advised that the developer use their own storage.
IMPORTANT: When handling user input such as attachments, please verify that the attachment is free of inappropriate content and is what your bot expected to receive.
IMPORTANT: When dealing with personal data, please respect user privacy. Follow platform guidelines and post your privacy statement online.
You can browse to https://webchat-sample-upload-to-azure.azurewebsites.net/ to try out the hosted demo.
This demo integrates with multiple services. There are multiple services you need to setup in order to host the demo.
To host this demo, you will need to clone the code and run locally.
This will create a new Azure Storage for temporary storage of user uploads.
We prefer to use Bot Channel Registration during development. This will help you diagnose problems locally without deploying to the server and speed up development.
You can follow our instructions on how to setup a new Bot Channel Registration.
When you are building your production bot, never expose your Web Chat or Direct Line secret to the client. Instead, you should use the secret to generate a limited token and send it to the client. For information, please refer the documentation on Direct Line token generation and the Enhanced Direct Line Authentication feature.
During development, you will run your bot locally. Azure Bot Services will send activities to your bot thru a public URL. You can use ngrok to expose your bot server on a public URL.
ngrok http -host-header=localhost:3978 3978
az bot update --resource-group <your-bot-rg> --name <your-bot-name> --subscription <your-subscription-id> --endpoint "https://a1b2c3d4.ngrok.io/api/messages"
webfolder, run the following
/bot/is the bot server
/web/is the REST API for distributing Shared Access Signature tokens
GET /api/directline/tokenwill generate a new Direct Line token for the React app
GET /api/azurestorage/uploadsastokenwill generate a new Shared Access Signature token for the web app to upload a file
This sample includes multiple parts:
When end-user start uploading files, Web Chat will dispatch
WEB_CHAT/SEND_FILES action. In our web app, we will intercept this action. Instead, we will read each attachment as
ArrayBuffer and upload to Azure Storage using SAS token.
After all attachments are uploaded to Azure Storage, we will send an event activity named
upload to the bot with the array of URLs pointing to every attachment.
Note: the SAS token allows user to upload huge files that may incurs unexpected charges to your system. You should take countermeasures against abuse. For example, using reverse-proxy, removing files more frequently, or capping the size that your system can handle per hour based on certain demographic data.
It is critical to verify the uploaded files before continue processing them in your system.
When the bot receive event activity named
upload, it will start validating the content of the file, and respond to the end-user with the result of validation.
In our sample, we will only read metadata and properties from each blob, and respond with a thumbnail card.
In your production system, you should always verify if the uploaded file is valid and contains appropriate content. To continue processing the files, you should copy the uploaded files into a separate container. You can use Azure Service Bus or Azure Queue Storage for long-processing jobs.
We will use [Lifecycle Management] feature from Azure Storage. For details, you can read this article.
.env file hold the environment variable critical to run the service. These are usually security-sensitive information and must not be committed to version control. Although we recommend to keep them in Azure Key Vault, for simplicity of this sample, we would keep them in
To ease the setup of this sample, here is the template of
AZURE_STORAGE_ACCOUNT_NAME=youraccountname AZURE_STORAGE_ACCOUNT_KEY=a1b2c3d MICROSOFT_APP_ID=12345678-1234-5678-abcd-12345678abcd MICROSOFT_APP_PASSWORD=a1b2c3d4e5f6
AZURE_STORAGE_ACCOUNT_NAME=youraccountname AZURE_STORAGE_ACCOUNT_KEY=a1b2c3d DIRECT_LINE_SECRET=a1b2c3.d4e5f6g7h8i9j0
Currently, DirectLineJS (0.11.4) will inspect every outgoing activity. If the
attachments array is not empty, it will read the
contentURL from every attachment, download the content as
Blob using the
contentURL, and then send a multipart message to the Direct Line channel. Today, the
contentURL is constructed by converting a
File object into a URL through the
URL.createObjectURL function and is prefixed with
Thus, if we use
attachments array to send blob URLs to the bot, DirectLineJS will try to re-download every file and send it to Direct Line channel again.
As there are no workarounds for this behavior, we will need to use a mechanism other than the
Since revoking the URL created through
createObjectURL is not trivial, there is a possibility that in the future we might change this behavior in DirectLineJS to use