Microsoft bot framework : How to define the image path which exists in the solution itself - bots

I have stored the image inside the project itself, now I would like to display the image on the hero card, so I have mentioned the relative path. However the image is not appearing....
List<CardImage> cardImages = new List<CardImage>();
cardImages.Add(new CardImage(url: "~/duck-on-a-rock.jpg", alt:"image1"));
But when I referred the image from some website and mention the same path on the page like below that time the image is appearing.
List<CardImage> cardImages = new List<CardImage>();
cardImages.Add(new CardImage(url: "http://www.publicdomainpictures.net/pictures/30000/t2/duck-on-a-rock.jpg", alt:"image1"));
Is it not possible to keep the image inside the project folder?

This is a super old question, but google me brought here nonetheless. The solution I came across was to create a data url for your local resource. In node.js:
const imageData = fs.readFileSync(path.join(__dirname, '../resources/logo.png'));
const base64Image = Buffer.from(imageData).toString('base64');
const inlinePng = {
name: 'logo.png',
contentType: 'image/png',
contentUrl: `data:image/png;base64,${ base64Image }`
};
With an svg, you can skip the base64 encode:
const svgData = fs.readFileSync(path.join(__dirname, './resources/logo.svg'));
const inlineSvg = {
name: 'logo',
contentType: 'image/svg',
contentUrl: `data:image/svg+xml;utf8,${ svgData }`,
};
See Microsoft's docs for reference and C# samples.

Using DI approach: Pass one extra IHostingEnvironment variable to your dialog constructor.
public DialogBot(ConversationState conversationState, T dialog, ConcurrentDictionary<string, ConversationReference> conversationReferences, IHostingEnvironment env)
{
_conversationReferences = conversationReferences;
_conversationState = conversationState;
_dialog = dialog;
_env = env;
}
And later you can use _env.WebRootPath to access your local storage (for bot emulator) or use environmental variable WEBSITE_HOSTNAME if you run bot in azure.
private async Task SendWelcomeCardAsync(ITurnContext turnContext, CancellationToken cancellationToken)
{
var card = new HeroCard();
card.Title = "Welcome to Bot Framework!";
var host = new Uri(Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME") != null ? ("https://" + Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME")) : _env.WebRootPath + "/");
var img = new Uri(host, "MyImage.jpg");
card.Images = new List<CardImage>() { new CardImage(img.AbsoluteUri) };
var response = MessageFactory.Attachment(card.ToAttachment());
await turnContext.SendActivityAsync(response, cancellationToken);
}
I simply dropped MyImage.jpg image to wwwroot project folder and marked it as Content

Related

How to get parent folder for a subfolder in Autodesk BIM360 using Forge and Nodejs

I am looking into getting Parent Folder data for subfolders in BIM 360 using Nodejs and Forge
I see the method in Forge
GET https://developer.api.autodesk.com/data/v1/projects/:project_id/folders/:folder_id/parent
How to implement this code similar to the GetItemDetails:
async function getItemInfo(client, projectId, itemId) {
var itemdetails = await client.getItemDetails(projectId, itemId);
var temp = itemdetails.folder;
return temp;
}
It's quite straightforward.
Find the folder where the item you want is via calling https://forge.autodesk.com/en/docs/data/v2/reference/http/projects-project_id-items-item_id-parent-GET/. Here is the code snippet of using Forge nodejs client SDK:
const { FoldersApi, ItemsApi } = require('forge-apis');
const items = new ItemsApi();
const itemParentFolderContents = await items.getItemParentFolder(projectId, itemId, {}, oauthClient, credentials);
const itemParentFolderData = itemParentFolderContents.body.data;
Then you can call the parent folder endpoint you mentioned to get the folder parent of the folder where the item is located at.
https://forge.autodesk.com/en/docs/data/v2/reference/http/projects-project_id-folders-folder_id-parent-GET/ Here is the code snippet of using Forge nodejs client SDK:
const folders = new FoldersApi();
const parentFolderContents = await folders.getFolderParent(projectId, itemParentFolderData.id, {}, oauthClient, credentials);
const parentFolderData = parentFolderContents.body.data;

How to upload image to Azure Blob Storage with proper content type

I've read most of the documentation provided by MS to upload files/image to Blob Storage. It's been two days now and I'm stuck. I don't find an appropriate way to upload image with proper content-type. The file/image is uploaded but the content-type after upload to BLOB Storage is changed to 'application/octet-stream'. I want it to be 'image/png' or 'image/jpg' etc. for an image.
There are samples of C# code but they are not useful.
I'm trying with node.js
SDK Library Used : #azure/storage-blob
References :
https://azuresdkdocs.blob.core.windows.net/$web/javascript/azure-storage-blob/12.0.1/classes/blockblobclient.html#uploadfile
https://learn.microsoft.com/en-us/javascript/api/#azure/storage-blob/blockblobclient?view=azure-node-latest
Sample Code :
const bc = new BlockBlobClient(
rhcConfig.STORAGE_CONNECTION_STRING,
rhcConfig.CONTAINER_NAME,
`IMAGES/${fileName}`
);
// let result = await bc.uploadFile(_file);
// console.log(result);
const buff = Buffer.from(file, "base64");
const stream = getStream(buff);
const streamLength = buff.length;
await bc.uploadStream(stream, streamLength, 1, { httpHeaderOptions });
httpHeaderOptions :
const httpHeaders = {
"x-ms-blob-cache-control": "1000",
"x-ms-blob-content-type": "image/png",
"x-ms-blob-content-md5": `${md5Hash}`,
"x-ms-blob-content-encoding": "compress",
"x-ms-blob-content-language": "en",
"x-ms-blob-content-disposition": "multipart/form-data",
};
const httpHeaderOptions = { blobHTTPHeaders: httpHeaders };
Thanks to the community !!
Suppose your httpHeaderOptions format is not correct, you could refer to this interface description:BlobHTTPHeaders, below is my test code.
const blobServiceClient = BlobServiceClient.fromConnectionString(connectionstr)
const containerClient=blobServiceClient.getContainerClient('test')
const blobclient=containerClient.getBlockBlobClient('test.jpg')
let fileStream = fs.createReadStream('E:\\dog.jpg');
const blobOptions = { blobHTTPHeaders: { blobContentType: 'image/jpg' } };
blobclient.uploadStream(fileStream,undefined ,undefined ,blobOptions)
I had a similar issue and like the original poster found the micosoft documnetation and examples rather shockingly bad. I would have thought uploading images is a rather common thing to do but none of their examples show up to change the content type using the newer storage api. Anyhow, my implementation was simliar to George Chen's and is as follows`
BlobClient blobClient = photoContainer.GetBlobClient(fileName);
blobClient.UploadAsync(f.InputStream, new BlobHttpHeaders { ContentType = "image/jpeg" }).`

Issue in attachment upload in BOT emulator of Bot framework

I am uploading an attachment in BOT emulator, after uploading an attachment I am converting it to base64, to pass it to our service.
I pick this attachment from path D:\Images\MobileRequest.PNG, but after uploading it to BOT app it shows the path of attachment as http://127.0.0.1:44185/v3/attachments/ne7djbemc9f40bifi/views/original/MobileRequest.PNG, as the image is not available on this path, So while converting the image to base64, it throws an error as "URI formats are not supported.".
How to get actual physical path i.e "D:\Images\MobileRequest.PNG" in BOT app.
Below is code from my BOT app
var dialog = new PromptDialog.PromptAttachment("Please attach screenshot ", "Sorry, I didn't get the attachment. Try again please.", 2);
context.Call(dialog, afterUpload);
private async Task afterUpload(IDialogContext context, IAwaitable<IEnumerable<Attachment>> result)
{
IEnumerable<Attachment> attach = await result;
string filePath = attach.FirstOrDefault().ContentUrl + "/" + attach.FirstOrDefault().Name;
context.UserData.SetValue("filePath", filePath);
}
string filePath = string.Empty;
context.UserData.TryGetValue("filePath", out filePath);
using (System.Drawing.Image image = System.Drawing.Image.FromFile(filePath))
{
using (MemoryStream m = new MemoryStream())
{
image.Save(m, image.RawFormat);
byte[] imageBytes = m.ToArray();
attach1 = Convert.ToBase64String(imageBytes);
}
}
Your bot will be deployed so you will not have access to local files.
You can easily convert your image located at a URL by doing the following:
using (var client = new HttpClient())
{
var bytes = await client.GetByteArrayAsync(imageUrl);
var imageInBase64String = "image/jpeg;base64," + Convert.ToBase64String(bytes);
// Do what you want with your converted image
}

Microsoft Bot Framework WebChat: Add bot image

How to add image of the bot with some welcome text in the middle in Microsoft Bot Framework Web Chat. Seems like quite common functionality and I see images which indicates that is possible.
Anyone knows how to add it?
you can use the below code and replace your image path to give response from bot to user including text and image.
await context.PostAsync("Here we go with the welcome message\n"+"![AN IMAGE!](Your_Image_URL)");
Another way is, you can also use Card functionality:
private async Task Greeting(IDialogContext context, IAwaitable<IMessageActivity> argument)
{
var message = await argument;
if (string.IsNullOrEmpty(message.Text))
{
// Hero Card
var cardMsg = context.MakeMessage();
var attachment = BotWelcomeCard("Hello,I am a bot.", "");
cardMsg.Attachments.Add(attachment);
await context.PostAsync(cardMsg);
}
else
{
// else code
}
}
private static Attachment BotWelcomeCard(string responseFromQNAMaker, string userQuery)
{
var heroCard = new HeroCard
{
Title = userQuery,
Subtitle = "",
Text = responseFromQNAMaker,
Images = new List<CardImage> { new CardImage("../img/bot.gif") },
Buttons = new List<CardAction> { new CardAction(ActionTypes.ImBack, "Show Menu", value: "Show Bot Menu") }
};
return heroCard.ToAttachment();
}
ok, here is what we end up doing:
<script>
$(document).ready(function () {
$(".wc-header").append("<div class='wc-header-welcome'><img src='/Images/bot.png'/><div>Hello! I am your bot</div>");
});
</script>
Hope it will help save time to someone else.

Sharing image via my app in xamarin.forms

I want to share an image. Sharing options should contain my app xyz. For example if I open an image and want to share it on instagram sharing options contains instagram,facebook,twitter,email etc. Like that my app should be in sharing options. How can I do that in xamarin.forms(both ios and android).
I think the app icon is created in a directory that is private to your app, so other apps wont be able to get at it.
You will need to save it out somewhere where the other apps can access it then share it from that location some thing like this:
public void Share (string title, string content)
{
if (string.IsNullOrEmpty (title) || string.IsNullOrEmpty (content))
return;
Bitmap b = BitmapFactory.DecodeResource(Resources,Resource.Drawable.icon_120);
var tempFilename = "test.png";
var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filePath = System.IO.Path.Combine(sdCardPath, tempFilename);
using (var os = new FileStream(filePath, FileMode.Create))
{
b.Compress(Bitmap.CompressFormat.Png, 100, os);
}
b.Dispose ();
var imageUri = Android.Net.Uri.Parse ($"file://{sdCardPath}/{tempFilename}");
var sharingIntent = new Intent ();
sharingIntent.SetAction (Intent.ActionSend);
sharingIntent.SetType ("image/*");
sharingIntent.PutExtra (Intent.ExtraText, content);
sharingIntent.PutExtra (Intent.ExtraStream, imageUri);
sharingIntent.AddFlags (ActivityFlags.GrantReadUriPermission);
StartActivity (Intent.CreateChooser (sharingIntent, title));
}
Also add ReadExternalStorage and WriteExternalStorage permissions to your app.
Let me know if that works.

Resources