How to return an image to the client using Nest.js framework? - image

I am building an application, currently facing a problem I want to return an images which is stored in my server. I want to return image to React client, then it would be rendered in my component. But I can't figure out how to return the image itself. As far as I understand, I need to return image as JSON? But can't figure out how to do it in Nest.js framework.

First you should have a service, to serve static files. You can achieve this with Nest.JS. For example, if your images are placed in a public folder, placed in the root of your project, simply you can serve it, by adding the following line to your main.ts file:
import { join } from 'path';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use('/public', express.static(join(__dirname, '..', 'public'))); // <-
await app.listen(3000);
}
Then for example you have cat.png placed in the public folder, and you want to send this in your response, you can send something like this:
{
image: `${baseUrl}/public/cat.png`
}
For example for your local server, baseURL will be http://localhost:3000.
You can take a look at this article for more detailed explanations.

Related

Send multiple files to Slack via API

According to Slack's documentation is only possible to send one file per time via API. The method is this: https://api.slack.com/methods/files.upload.
Using Slack's desktop and web applications we can send multiple files at once, which is useful because the files are grouped, helping in the visualization when we have more than one image with the same context. See the example below:
Do you guys know if it's possible, via API, to send multiple files at once or somehow achieve the same results as the image above?
Thanks in advance!
I've faced with the same problem. But I've tried to compose one message with several pdf files.
How I solved this task
Upload files without setting channel parameter(this prevents publishing) and collect permalinks from response. Please, check file object ref. https://api.slack.com/types/file. Via "files.upload" method you can upload only one file. So, you will need to invoke this method as many times as you have files to upload.
Compose message using Slack markdown <{permalink1_from_first_step}| ><{permalink2_from_first_step}| > - Slack parse links and automatically reformat message
Here is an implementation of the procedure recommended in the other answer in python
def postMessageWithFiles(message,fileList,channel):
import slack_sdk
SLACK_TOKEN = "slackTokenHere"
client = slack_sdk.WebClient(token=SLACK_TOKEN)
for file in fileList:
upload=client.files_upload(file=file,filename=file)
message=message+"<"+upload['file']['permalink']+"| >"
outP = client.chat_postMessage(
channel=channel,
text=message
)
postMessageWithFiles(
message="Here is my message",
fileList=["1.jpg", "1-Copy1.jpg"],
channel="myFavoriteChannel",
)
A Node.JS (es6) example using Slack's Bolt framework
import pkg from '#slack/bolt';
const { App } = pkg;
import axios from 'axios'
// In Bolt, you can get channel ID in the callback from the `body` argument
const channelID = 'C000000'
// Sample Data - URLs of images to post in a gallery view
const imageURLs = ['https://source.unsplash.com/random', 'https://source.unsplash.com/random']
const uploadFile = async (fileURL) {
const image = await axios.get(fileURL, { responseType: 'arraybuffer' });
return await app.client.files.upload({
file: image.data
// Do not use "channels" here for image gallery view to work
})
}
const permalinks = await Promise.all(imageURLs.map(async (imageURL) => {
return (await uploadImage(imageURL)).file.permalink
}))
const images = permalinks.map((permalink) => `<${permalink}| >`).join('')
const message = `Check out the images below: ${images}`
// Post message with images in a "gallery" view
// In Bolt, this is the same as doing `await say({`
// If you use say(, you don't need a channel param.
await app.client.chat.postMessage({
text: message,
channel: channelID,
// Do not use blocks here for image gallery view to work
})
The above example includes some added functionality - download images from a list of image URLs and then upload those images to Slack. Note that this is untested, I trimmed down the fully functioning code I'm using.
Slack's image.upload API docs will mention that the file format needs to be in multipart/form-data. Don't worry about that part, Bolt (via Slack's Node API), will handle that conversion automatically (and may not even work if you feed it FormData). It accepts file data as arraybuffer (used here), stream, and possibly other formats too.
If you're uploading local files, look at passing an fs readstream to the Slack upload function.
For Python you can use:
permalink_list = []
file_list=['file1.csv', 'file2.csv', 'file3.csv']
for file in file_list:
response = client.files_upload(file=file)
permalink = response['file']['permalink']
permalink_list.append(permalink)
text = ""
for permalink in permalink_list:
text_single_link = "<{}| >".format(permalink)
text = text + text_single_link
response = client.chat_postMessage(channel=channelid, text=text)
Here you can play around with the link logic - Slack Block Kit Builder
Python solution using new recommended client.files_upload_v2 (tested on slack-sdk-3.19.5 on 2022-12-21):
import slack_sdk
def slack_msg_with_files(message, file_uploads_data, channel):
client = slack_sdk.WebClient(token='your_slack_bot_token_here')
upload = client.files_upload_v2(
file_uploads=file_uploads_data,
channel=channel,
initial_comment=message,
)
print("Result of Slack send:\n%s" % upload)
file_uploads = [
{
"file": path_to_file1,
"title": "My File 1",
},
{
"file": path_to_file2,
"title": "My File 2",
},
]
slack_msg_with_files(
message='Text to add to a slack message along with the files',
file_uploads_data=file_uploads,
channel=SLACK_CHANNEL_ID # can be found in Channel settings in Slack. For some reason the channel names don't work with `files_upload_v2` on slack-sdk-3.19.5
)
(some additional error handling would not hurt)
Simply use Slack Blocks: Block Kit Builder. Great feature for the message customizations.

PostAsync hanging in Xamarin Forms works on emulator but hangs on actual Mobile phone

I have Xamarin Forms project where I'm trying to POST and GET data to/from a Web API but when I'm making an async/await call, it works on the emulator (not without its original problems!) but when I try it on my actual phone mobile (Samsung S8+), it just hangs indefinitely.
Note that I'm only concentrating on the Android part right now, not iOS, not that the problem should make any difference in either.
This is the code I'm using:
IDataService.cs
Task<TResponse> PostDataAsync<TRequest, TResponse>(string uri, TRequest data)
where TRequest : class
where TResponse : class;
DataService.cs:
public async Task<TResponse> PostDataAsync<TRequest, TResponse>(string
additionalUri, TRequest data)
where TRequest : class
where TResponse : class
{
return await WebClient
.PostData<TRequest, TResponse>
(string.Concat(this.Uri, additionalUri), data);
}
WebClient.cs
using (var client = new HttpClient())
{
var jsonData = JsonConvert.SerializeObject(data);
using (var response = await client.PostAsync(
uri,
new StringContent(jsonData,
Encoding.UTF8,
"application/json" )))
{
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<TResponse>(content);
}
}
}
Method 1:
LoginPageViewModel.cs
public DelegateCommand SignInCommand => _signInCommand ??
(this._signInCommand = new DelegateCommand(SignInCommandAction));
private async void SignInCommandAction()
{
try
{
....
var user = await this._dataService
.PostDataAsync<LoginRequestDto,
LoginResponseDto>(#"Accounts/Login", loginRequestDto);
....
}
...
}
Method2:
LoginPageViewModel.cs
public DelegateCommand SignInCommand => _signInCommand ??
(this._signInCommand =
new DelegateCommand(async () => await SignInCommandAction()));
private async Task SignInCommandAction()
{
try
{
....
var user = await this._dataService
.PostDataAsync<LoginRequestDto,
LoginResponseDto>(#"Accounts/Login", loginRequestDto);
....
}
...
}
The PostDataAsync works with both methods when I call my local web API i.e. http://10.0.2.2/MyApp/api/ but both methods still hangs when calling external my web service from web provider i.e. http://myapp-123-site.atempurl.com/api/ which is a temp url for testing purpose.
The same apply to my GetDataAsync which is not demonstrated in question but I just thought I'd mention it.
Based on the above, you would think that my async/await code is correct since it works when calling the local web api but then what's causing it to hang when calling the remote web api.
As mentioned, I did enable my INTERNET permission in the manifest.
Any suggestions welcomed?
Thanks.
UPDATE-1:
Note that I've just tried to call a GET opertation within the same function and this is working in the emulator but hanging with the actual mobile.
using (var client = new HttpClient())
{
using (var response = await client.GetAsync(uri))
{
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
return Newtonsoft.Json.JsonConvert
.DeserializeObject<TResponse>(content);
}
}
}
UPDATE-2:
This is somehow working and I have no idea why! The only thing that comes to mind is that I upgraded my libraries. This included PRISM which may have been at the source of the problem but I have no idea.
Sorry I can't provide more details. I could role back my code and try to see if it's hanging again but I just don't have the time to go and experiment some more considering the amount of time I've already spent on this. Sorry.
The requested url is an IP or a domain name.
If it is ip, only the IP of the public network can be accessed by devices on multiple network segments.
If it is a domain name, it needs to support the domain name resolution service.
If you do not have these environments for a while, you need the IP of the device and the IP of the server on the same network segment.
The PostDataAsync works with both methods when I call my local web API i.e. http://10.0.2.2/MyApp/api/ but both methods still hangs when calling external my web service from web provider i.e. http://myapp-123-site.atempurl.com/api/ which is a temp url for testing purpose.
From this phenomenon , the reason should be the temp url. From this domain name (myapp-123-site.atempurl.com) can not find the right local IP (10.0.2.2).And when you test in local network , I guess this will work.However the network of actual mobile can be not the same with local network , such as using 3G/4G network , then this will not working.

How to test ImagePicker in Flutter Driver?

In Flutter integration testing, how can we handle ImagePicker? as well as other platform related plugins?
Finally, I got a solution for this question.
this is the code in app.dart:
prepare an image file in assets, for example: images/sample.png.
import 'dart:io';
import 'dart:typed_data';
import 'package:path_provider/path_provider.dart';
import 'package:image_picker_test/main.dart' as app;
import 'package:flutter_driver/driver_extension.dart';
import 'package:flutter/services.dart';
void main() {
// This line enables the extension.
enableFlutterDriverExtension();
const MethodChannel channel =
MethodChannel('plugins.flutter.io/image_picker');
channel.setMockMethodCallHandler((MethodCall methodCall) async {
ByteData data = await rootBundle.load('images/sample.png');
Uint8List bytes = data.buffer.asUint8List();
Directory tempDir = await getTemporaryDirectory();
File file = await File('${tempDir.path}/tmp.tmp', ).writeAsBytes(bytes);
print(file.path);
return file.path;
});
app.main();
}
Frank Yan's solution works fine. Basically he is using MethodChannel as an interceptor of request to ImagePicker
MethodChannel('plugins.flutter.io/image_picker')
In this part he defines which plugin has to be mocked
channel.setMockMethodCallHandler((MethodCall methodCall) async {
ByteData data = await rootBundle.load('images/sample.png');
Uint8List bytes = data.buffer.asUint8List();
Directory tempDir = await getTemporaryDirectory();
File file = await File('${tempDir.path}/tmp.tmp', ).writeAsBytes(bytes);
print(file.path);
return file.path;
});
This function defines what has to be returned from request to image picker plugin. So your program will do these actions each time when user uses image picker. Right here it will just return the image from 'images/sample.png'. In my case I had to put image into assets/image.png in my project root. Anyway you can mock any plugin like that. I had to also mock cropper plugin which is called after image picker ends it's job.
**Note: **mocking is not the best way to go with e2e or as they are called in flutter integration tests. I used it just because there is no workaround (I couldn't find it) at the moment and I am blocked with step of picture upload in my scenario. So be careful with using such approach.
You don't need to call this function anywhere in test. Your app will run with mocked plugin that we define in MethodChannel constuctor MethodChannel('');

Sending partials from keystone.js for use with ui.view

Been trying to get my head around this, but can't for the life of me figure out what I'm missing.
So I want to set up keystone, but want to use angular on the front end, and I want to avoid reloading the page every time.
Got angular running quite fine and pretty quickly. But now I am trying to set up the routes on the backend for the partials, and while I can manage to get them set up to answer, I can not get them to just send the partial, whatever I do it sends the whole page back to me. with html, body, head.
So far I have managed to figure out that I need a route, so imported my uiview directory and added the following route:
var keystone = require('keystone');
var middleware = require('./middleware');
var importRoutes = keystone.importer(__dirname);
// Common Middleware
keystone.pre('routes', middleware.initLocals);
keystone.pre('render', middleware.flashMessages);
// Import Route Controllers
var routes = {
views: importRoutes('./views'),
uiviews: importRoutes('/uiviews'),
};
// Setup Route Bindings
exports = module.exports = function (app) {
// Views
app.get('/', routes.views.index);
app.get('/uiviews/index',routes.uiviews.index);
app.get('/blog/:category?', routes.views.blog);
app.get('/blog/post/:post', routes.views.post);
app.get('/gallery', routes.views.gallery);
app.all('/contact', routes.views.contact);
// NOTE: To protect a route so that only admins can see it, use the requireUser middleware:
// app.get('/protected', middleware.requireUser, routes.views.protected);
};
I think what is happening is that the pre compiler ( keystone.pre('routes', middleware.initLocals);) gets hold of it and wraps it all the way it thinks it is suppose to, but I'm not certain.
I even tried to create a uiviews.js in ./routes with just my uiroute, but that gives me 404 errors
var keystone = require('keystone');
var middleware = require('./middleware');
var importRoutes = keystone.importer(__dirname);
// Import Route Controllers
var routes = {
uiviews: importRoutes('/uiviews'),
};
// Setup Route Bindings
exports = module.exports = function (app) {
// Views
console.log('uiroutes added');
app.get('/uiview/index',routes.uiviews.index);
// NOTE: To protect a route so that only admins can see it, use the requireUser middleware:
// app.get('/protected', middleware.requireUser, routes.views.protected);
};
Any ideas?
This is more of a Express question and not of keystone.Js.
You have not said which router you want partially. and neither shared rendering code of that handler.
Any way Make sure that the template you are using does not include any other template. particularly default.jade
I finally managed to figure out what I was missing.
Technically it is not keystone.js that controls what is sent, it is handlebars. This might be obvious to everyone but me.
However, the trick is to tell handlebars not to include the layout, which is done using {layout: false}. So my uiview route looks like this (last little line does the magic):
var keystone = require('keystone');
exports = module.exports = function(req, res) {
console.log("request for index received");
var view = new keystone.View(req, res),
locals = res.locals;
console.log(locals);
// Render the view
console.log(view)
view.render('uiviews/index', {layout: false});
};
with the index.js router looking like this:
var keystone = require('keystone');
var middleware = require('./middleware');
var importRoutes = keystone.importer(__dirname);
// Common Middleware
keystone.pre('routes', middleware.initLocals);
keystone.pre('render', middleware.flashMessages);
// Import Route Controllers
var routes = {
views: importRoutes('./views'),
uiviews: importRoutes('/uiviews'),
};
// Setup Route Bindings
exports = module.exports = function (app) {
// Views
console.log('index added');
app.get('/', routes.views.index);
app.get('/partners', routes.views.partners);
app.get('/blog/:category?', routes.views.blog);
app.get('/blog/post/:post', routes.views.post);
app.get('/gallery', routes.views.gallery);
app.get('/philosophy', routes.views.philosophy)
app.get('/socialmedia', routes.views.socialmedia)
app.all('/contact', routes.views.contact);
app.get('/uiviews/index', routes.uiviews.index)
// NOTE: To protect a route so that only admins can see it, use the requireUser middleware:
// app.get('/protected', middleware.requireUser, routes.views.protected);
};
And now you can call [host]/uiviews/index and only receive a partial route.

Precache / Preload directory

Been looking around for ways to preload a directory of images, found this to be the best script provided here: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/
I like this best as it waits for current document to load before preloading, but I'd like to get this guy to load a directory of images instead of having to specify each file, and am pretty new to javascript, any help appreciated.
function preloader() {
if (document.images) {
var img1 = new Image();
var img2 = new Image();
var img3 = new Image();
img1.src = "http://domain.tld/path/to/image-001.gif";
img2.src = "http://domain.tld/path/to/image-002.gif";
img3.src = "http://domain.tld/path/to/image-003.gif";
}
}
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
addLoadEvent(preloader);
There is no general way to accomplish this. You need some way to retrieve the contents of a directory from the server, and there is no guarantee that your web server will provide a listing. In general, most web servers do not allow a client to list the contents of a server side directory.
If you control the Web Server, you can configure it so that a directory listing is shown, for example, when you ask for "http://domain.tld/path/to/". But even then, the format of the returned response will likely be different, depending on the web server.
However, if you are able to get a listing of the images in a given directory from the server, you will still need to use some technique such as AJAX, or a hidden IFRAME, to load those image names. Then you could use JavaScript to iterate over the file names, construct the URL, and make an Image object for each.

Resources