NestJS req.body from POST method is empty/undefined when awaiting ArrayBuffer - post

I am trying to send file from Client (Angular) to the NestJS same way like it is working now with Java-springboot API.
I am using POST method in NestJS but, unfortunatelly I am not able to got any data from the body :
here is the code :
#Post('/uploadExportFile')
uploadAttachment(#Req() req: Request, #Body() attachment: ArrayBuffer): any {
console.log(attachment);
return {};
}
content-type is set in header on Client side, I am not sure if I need to set content-types there ? Content type depends on file mimetype it should be (application/pdf/png/jpeg)..not multiform or what I need to do to achieve that attachment object will not return empty {} .
req.body is undefined
What I need to do with that file is to again change it back to Base64 (in angular it is in Base64) but Java API consumes only byte[] so I need to keep that like it is on FE.
any suggestions what is wrong in this "simple" code?
** EDIT **
====↓ EDIT ↓====
Solution: request.body is undefined is:
NestJS use as default body jsonBody, so in that case you have to override for specific routes that you want to use raw-body, and if raw-body is used insted of jsonBody, then the body from request is not undefined and it contain ArrayBuffer.
What you need to do is something like this;
Create rawBody middleware raw-body.middleware.ts
import { Injectable, NestMiddleware } from '#nestjs/common';
import { Request, Response } from 'express';
import * as bodyParser from 'body-parser';
#Injectable()
export class RawBodyMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => any) {
bodyParser.raw({type: '*/*'})(req, res, next);
}
}
app.module.ts
export class AppModule implements NestModule {
public configure(consumer: MiddlewareConsumer): void {
consumer
.apply(RawBodyMiddleware)
.forRoutes({
path: '/uploadExportFile',
method: RequestMethod.POST,
})
.apply(JsonBodyMiddleware)
.forRoutes('*');
}
}
and you need to disable bodyparser in main.ts
const app = await NestFactory.create(AppModule, { bodyParser: false })
in new version of NestJS is introduced new option raw-body but I have no possibility to test that https://docs.nestjs.com/faq/raw-body#raw-body

frist thing send the content-type application/x-www-form-urlencoded
and sure you have add UseInterceptors Like FileInterceptor
you can import FileInterceptor
if you need to get buffer try use file.buffer
import {FileInterceptor} from "#nestjs/platform-express";
#Post('upload')
#UseInterceptors(FileInterceptor('file'))
async upload(#Req() request: RequestWithUser, #UploadedFile() file) {
if (!file) {
throw new HttpException('File is required', HttpStatus.BAD_REQUEST);
}
// you have file
return await this.storageService.upload(file, request.user);
}

Related

Dart server side: How to receive data from the Postman (form-data)?

I am using dart:io to create the server. I send the request from the Postman with form-data. I need to use form-data because my old API from another language uses it and the app uses it too.
At the moment. I am trying to get the data and files with this code:
Future main(List<String> arguments) async {
HttpServer server = await HttpServer.bind('localhost', 8085);
server.listen((HttpRequest request) async {
String jsonString = await request.cast<List<int>>().transform(utf8.decoder).join();
print("jsonString:\n$jsonString");
await request.response.close();
});
}
When I send the data and a file from the Postman with this below.
I will get the error below.
Unhandled exception:
FormatException: Unexpected extension byte (at offset 435)
If I don't send the file as image 1, I got this.
jsonString:
----------------------------166099235909119466948633
Content-Disposition: form-data; name="key 1"
Content-Type: application/json
value 1
----------------------------166099235909119466948633
Content-Disposition: form-data; name="key 2"
value 2
----------------------------166099235909119466948633--
I can't convert the above results to variables.
I don't know how to do that. Has anyone an example for doing this or suggest any package to me? This is my first time creating a dart server.
I follow this.
You can get the data and files from the request by using shelf_multipart (Other packages may be used in conjunction with this one and find more methods on GitHub).
If you want to see results quickly that it can be done. Follow this below.
I am using 3 packages including the shelf, shelf_router, and shelf_multipart packages.
You need to add these packages to your pubspec.yaml.
(You can copy and paste these into your pubspec.yaml.)
dependencies:
shelf: ^1.4.0
shelf_router: ^1.1.3
shelf_multipart: ^1.0.0
Then copy my code and past it to your main.dart:
import 'dart:convert';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_router/shelf_router.dart';
import 'package:shelf_multipart/form_data.dart';
import 'package:shelf_multipart/multipart.dart';
Future main(List<String> arguments) async {
final service = Service();
final server = await shelf_io.serve(service.handler, 'localhost', 8085);
print('Server running on localhost:${server.port}');
}
class Service {
Handler get handler {
final router = Router();
router.post("/example", (Request request) async {
if (request.isMultipart && request.isMultipartForm) {
Map<String, dynamic>? data = await RequestConverter.formData(request);
return data != null
? Response.ok("form-data: true, receive-data: true, data: $data")
: Response.ok("form-data: true, receive-data: false");
}
return Response.ok("form-data: false");
});
router.all('/<ignored|.*>', (Request request) {
return Response.notFound('Page not found');
});
return router;
}
}
class RequestConverter {
static Future<Map<String, dynamic>?> formData(Request request) async {
try {
Map<String, dynamic> data = {};
Map<String, dynamic> files = {};
final List<FormData> formDataList = await request.multipartFormData.toList();
for (FormData formData in formDataList) {
if (formData.filename == null) {
String dataString = await formData.part.readString();
data[formData.name] = Json.tryDecode(dataString) ?? dataString; //Postman doesn't send data as json
} else if (formData.filename is String) {
files[formData.name] = await formData.part.readBytes();
}
}
return {"data": data, "files": files};
} catch (e) {
return null;
}
}
}
class Json {
static String? tryEncode(data) {
try {
return jsonEncode(data);
} catch (e) {
return null;
}
}
static dynamic tryDecode(data) {
try {
return jsonDecode(data);
} catch (e) {
return null;
}
}
}
After this, you can start your server in your terminal. For me I am using:
dart run .\bin\main.dart
Finally, open the Postman and paste http://localhost:8085/example to the URL field, select the POST method, and form-data. You can add the data into the KEY and VALUE fields. Then press send.
This is my example in the Postman:
This solution work with http.MultipartRequest() from the Flutter app.

using headers in HTTP client

I am trying to develop a dashboard in angular 7. I wanted to access an URL and get the JSON response in my dashboard. the problem is that my code works fine with an open source URL. but there are few end points, which have authorization request. Aim is to add the headers like the JWT token, authorization to my service and display the data in my dashboard.
I found few resources on the internet which are confusing.
Below is my code I tried in my service.ts
import { Injectable } from '#angular/core';
import {HttpClient} from "#angular/common/http";
#Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) { }
getlocations() {
return this.http.get('https://jsonplaceholder.typicode.com/users')
}
}
Any lead on how to add the header and access them would be really helpful.
The simplest way is to modify a specific request by adding HttpHeaders with the authorization parameter. Here's an example:
getlocations() {
return this.http.get(
'https://jsonplaceholder.typicode.com/users',
{ headers: new HttpHeaders({'Authorization': 'Bearer ' + token}) }
);
}

Passing very large XML data as params in Angular 2 to Rails

I have a text area, where user can paste any XML. Then on click of a button, the XML is sent to the server to get the response. I find, this works perfectly with smaller XMLs. But, my issue is, when I send a large XML, the Rails server log simply says
!! Invalid
request
CODE
Provider.ts
import { Injectable } from '#angular/core';
import { Http, Headers, Response } from '#angular/http';
import { HttpClientService } from './../services/httpclient.service';
#Injectable()
export class QuestWebServiceTestProvider {
constructor(private http: HttpClientService) {}
getResponseXML(params) {
return this.http.get('/api/v1/get_response_xml?request_xml=' + params["request_xml"]);
}
}
Component.ts (this passes the XML read from textarea to provider)
getResponse() {
let requestXml = this.requestXmlElement.nativeElement.value.trim();
if(requestXml.length > 0) {
let requestXmlJson = encodeURI(requestXml);
this.<provider>.getResponseXML({request_xml: requestXmlJson).subscribe(
data => {
console.log(data);
}
)
}
}
What is the best way to send larger XMLs?
Sorry, for the typo in the question. I actually use POST request.
Thanks Pavel Mikhailyuk for pointing it.
This is how I fixed it:
Instead of framing the query params manually as:
...get_response_xml?request_xml=' + params["request_xml"]
I pass the XML as options to HTTP POST:
let options = {request_xml: params["request_xml"] };
return this.http.post('...get_response_xml?, options);
This seemed to work !!!

In dart httpRequest getstring always error

I established a RESTful server, and I can get a simple string with my Chrome or IE using this URL: "http://localhost:8080/WebService/RESTful/getString"
But when using Dart, it always returns a error message:
"[object XMLHttpRequestProgressEvent]"
From the onError() callback method,
I'm sure that server returns a string with "text/plain" MIME type in Java.
Here is the code:
import 'dart:html';
void main() {
HtmlElement btn = document.body.querySelector("#btn");
btn.onClick.listen(onClick);
}
void onClick(Event v) {
var url = "http://localhost:8080/WebService/RESTful/getString";
HttpRequest.getString(url).then((str) {
window.alert(str.toString());
}, onError: (e) {
window.alert(e);
});
}
Who can help me ?
If you try to fetch resources from another server than the one your page was loaded from, this server needs to return CORS headers otherwise your browser refuses to fetch form this other server.
It depends on your server how this can be configured or added.
See for example
- How do you add CORS headers in Redstone interceptor?
- CORS with Dart, how do I get it to work?

Using dart to download a file

Can we use dart to download a file?
For example in python
I'm using the HTTP package a lot. If you want to download a file that is not huge, you could use the HTTP package for a cleaner approach:
import 'package:http/http.dart' as http;
main() {
http.get(url).then((response) {
new File(path).writeAsBytes(response.bodyBytes);
});
}
What Alexandre wrote will perform better for larger files. Consider writing a helper function for that if you find the need for downloading files often.
Shailen's response is correct and can even be a little shorter with Stream.pipe.
import 'dart:io';
main() async {
final request = await HttpClient().getUrl(Uri.parse('http://example.com'));
final response = await request.close();
response.pipe(File('foo.txt').openWrite());
}
The python example linked to in the question involves requesting the contents of example.com and writing the response to a file.
Here is how you can do something similar in Dart:
import 'dart:io';
main() {
var url = Uri.parse('http://example.com');
var httpClient = new HttpClient();
httpClient.getUrl(url)
.then((HttpClientRequest request) {
return request.close();
})
.then((HttpClientResponse response) {
response.transform(new StringDecoder()).toList().then((data) {
var body = data.join('');
print(body);
var file = new File('foo.txt');
file.writeAsString(body).then((_) {
httpClient.close();
});
});
});
}
We can use http.readBytes(url).
await File(path).writeAsBytes(await http.readBytes('https://picsum.photos/200/300/?random'));
Yes, first of all you have to request to file url using http dart library like:
Response response = await get(Uri.parse(link));
after that your Response object (response) will get that file in self and you can simply write the response bytes to a file and that file will be your downloaded file.
as I open file like this:
File file = File('image.jpg')
then we have to send response bytes to this file like this:
file.writeAsBytes(response.bodyBytes);
now you have downloaded a image file successfully.. Congrates.
additional, for example let me show you a sample code to download a image file :
import 'dart:io';
import 'package:http/http.dart';
main(List<String> args) async {
var link =
"https://pps.whatsapp.net/v/t61.24694-
24/72779382_449683642563635_3243701117464346624_n.jpg?ccb=11-
4&oh=23e3bc2ce3f4940a70cb464494bbda76&oe=619B3B8C";
Response response = await get(Uri.parse(link));
File file = File('image.jpg');
file.writeAsBytes(response.bodyBytes);
}
look, this is the code and a file named image.jpg is downloaded at bottom in terminal view is our downloaded image.
screen shot
this is our actual image which we downloaded.
downloaded image

Resources