How to make HTTP POST call with application/zip and multipart/form-data using plugin io.github.http-builder-ng.http-plugin in Groovy - gradle-plugin

I am using the below code to make HTTP POST call to the server with the content type as application/zip and multipart/form-data using io.github.http-builder-ng.http-plugin.(One of the example shared here)
plugins {
id "io.github.http-builder-ng.http-plugin" version "0.1.1"
}
import groovyx.net.http.ApacheEncoders
import groovyx.net.http.*
import groovyx.net.http.HttpConfigs.BasicHttpConfig
import groovyx.net.http.OkHttpBuilder.OkHttpToServer
import static groovyx.net.http.MultipartContent.multipart
File msFile =new File("C:\\GradlePOC\\POC_1\\btest.zip");
OkHttpBuilder.configure {
request.uri = 'https://example.com'
request.auth.basic 'ABC', 'XXXXX'
request.encoder('application/zip'){ BasicHttpConfig config, OkHttpToServer req->
req.toServer(new FileInputStream(
msFile
))
}
}.post {
request.uri.path = '/application/applications/3547/binaries'
request.contentType = 'multipart/form-data'
request.body = multipart {
field 'name', 'data'
part 'filename', 'btest.zip', 'application/zip', msFile
}
request.encoder 'multipart/form-data', OkHttpBuilder.&multipart
}
But the above code is not working for me. Any help would be much appreciated.

Try with these changes:
plugins {
id "io.github.http-builder-ng.http-plugin" version "0.1.1"
}
import groovyx.net.http.HttpBuilder
import groovyx.net.http.MultipartContent
import groovyx.net.http.OkHttpEncoders
import groovyx.net.http.ChainedHttpConfig
import groovyx.net.http.ToServer
File msFile =new File("C:\\GradlePOC\\POC_1\\btest.zip");
OkHttpBuilder.configure {
request.uri = 'https://example.com'
request.auth.basic 'ABC', 'XXXXX'
request.encoder('application/zip'){ ChainedHttpConfig config, ToServer req->
req.toServer(new FileInputStream(msFile))
}
}.post {
request.uri.path = '/application/applications/3547/binaries'
request.contentType = 'multipart/form-data'
request.body = MultipartContent.multipart {
field 'name', 'data'
part 'filename', 'btest.zip', 'application/zip', msFile
}
request.encoder 'multipart/form-data', OkHttpEncoders.&multipart
}

Here is the only working way for me:
#Grapes([
#Grab('org.slf4j:slf4j-simple:1.7.25'),
#Grab('io.github.http-builder-ng:http-builder-ng-okhttp:1.0.4')
])
import groovyx.net.http.*
String BASE_URL = '[HOST_SERVER]'
String URI_PATH = '[UPLOAD_ENDPOINT]'
File msFile = new File('C:\\GradlePOC\\POC_1\\btest.zip')
// Post a file (okhttp)
OkHttpBuilder.configure {
request.uri = BASE_URL
request.auth.basic 'admin', 'admin'
}.post {
request.uri.path = URI_DOC_UPLOAD
request.contentType = 'multipart/form-data'
request.body = MultipartContent.multipart {
field 'name', 'data'
part 'filename', msFile.name, 'application/octet-stream', msFile
}
request.encoder 'multipart/form-data', OkHttpEncoders.&multipart
}
It worked for me to upload PDF files.

Related

React-Admin with .net .The response to 'getList' must be like { data : [{ id: 123, ...}, ...] }, but the received data items do not have an 'id' key

I have an ASP.NET Core Web API and a React client. I'm trying to build admin dashboard with React-Admin. My problem is when I receive the data from server, my object are with property Id (uppercase), then in console I'm getting an error
The response to 'getList' must be like { data : [{ id: 123, ...}, ...] }, but the received data items do not have an 'id' key
I tried making new test class with property id (lowercase) in my server and then the problem is gone.
How can I fix this issue?
This is my test class and its working.
public class CityModel
{
public string id { get; set; }
public string Name { get; set; }
}
[HttpGet("Cities")]
public CityModel[] GetCities()
{
var city1 = new CityModel()
{
id = "ahsxge",
Name = "Berlin"
};
var city2 = new CityModel()
{
id = "axhdagw",
Name = "London"
};
var list = new List<CityModel>();
list.Add(city1);
list.Add(city2);
Response.Headers.Add("Access-Control-Expose-Headers", "X-Total-Count");
Response.Headers.Add("X-Total-Count", list.Count.ToString());
return list.ToArray();
}
This is my component in react :
const AppAdmin = () => {
const jwt = localStorage.getItem("jwt");
const httpClient = (url, options = {}) => {
options.user = {
authenticated: true,
token: 'Bearer ' + jwt
};
return fetchUtils.fetchJson(url, options);
};
const dataProvider = jsonServerProvider('https://localhost:44366/api', httpClient);
dataProvider.getList('Cities/Cities', {
pagination: { page: 1, perPage: 15 },
sort: { field: 'Name', order: 'ASC' },
})
.then(response => console.log(response));
return (
<Admin dataProvider={dataProvider}>
<Resource name='Cities/Cities' list={CitiesList} />
</Admin>
)
}
export default AppAdmin
You can configure the json converter to use camelCase serialization int the ConfigureServices method in the Startup.cs file the following way:
services
.AddControllers()
.AddJsonOptions(opts =>
{
opts.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
})
This way you can use PascalCase properties in your c# code (which you should do), but your client will recieve camelCase json properties.

Devexpress file manager using asp.net file system provider

I implemented devextreme to my react project.I'm using file manager system and I'm using devexpress for create system provider with my asp.net project.
I have an issue.
When i try to upload any file I'm getting and error.Download,move,copy is working very well.But i cant upload any file.
File uploaded succesfully my temp folder but then doesnt move to my real path.How can i fix this.Devexpress version 20.1
public object FileSystem(long id, FileSystemCommand command, string arguments, HttpRequest Request)
{
var path = Path.Combine(HostingEnvironment.ContentRootPath, "../files/Images/", id.ToString());
var config = new FileSystemConfiguration
{
Request = Request,
FileSystemProvider = new PhysicalFileSystemProvider(
path,
(fileSystemItem, clientItem) =>
{
if (!clientItem.IsDirectory)
clientItem.CustomFields["url"] = GetFileItemUrl(fileSystemItem, Request);
}
),
//uncomment the code below to enable file/folder management
AllowCopy = true,
AllowCreate = true,
AllowMove = true,
AllowDelete = true,
AllowRename = true,
AllowUpload = true,
AllowDownload = true,
AllowedFileExtensions = new[] { ".txt", ".pdf", ".doc", ".docx", ".xls", ".xlsx", ".png", ".jpg", ".jpeg", ".gif", ".csv" }
};
var processor = new FileSystemCommandProcessor(config);
var result = processor.Execute(command, arguments);
return result.GetClientCommandResult();
}
Here is the front end code
import React from "react";
import FileManager, { Permissions } from "devextreme-react/file-manager";
import RemoteFileSystemProvider from "devextreme/file_management/remote_provider";
import { Popup } from "devextreme-react/popup";
let remoteProvider = new RemoteFileSystemProvider({
endpointUrl: "https://myapiurl.com.tr/api/FileManager/FileSystem/121",
});
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
currentPath: "Widescreen",
popupVisible: false,
imageItemToDisplay: {},
remoteProvider: new RemoteFileSystemProvider({
endpointUrl: "https://myapiurl.com.tr/api/FileManager/FileSystem/121",
}),
};
this.displayImagePopup = this.displayImagePopup.bind(this);
this.hideImagePopup = this.hideImagePopup.bind(this);
this.onCurrentDirectoryChanged = this.onCurrentDirectoryChanged.bind(this);
}
displayImagePopup(e) {
this.setState({
popupVisible: true,
imageItemToDisplay: {
name: e.file.name,
url: e.file.dataItem.url,
},
});
}
hideImagePopup() {
this.setState({
popupVisible: false,
});
}
onCurrentDirectoryChanged(e) {
this.setState({
currentPath: e.component.option("currentPath"),
});
}
render() {
console.log(remoteProvider);
return (
<>
{this.props.investment ? (
<div>
<FileManager
currentPath={this.state.currentPath}
fileSystemProvider={remoteProvider}
onSelectedFileOpened={this.displayImagePopup}
onCurrentDirectoryChanged={this.onCurrentDirectoryChanged}
>
<Permissions
create={true}
copy={true}
move={true}
delete={true}
rename={true}
upload={true}
download={true}
></Permissions>
</FileManager>
<Popup
maxHeight={600}
closeOnOutsideClick={true}
title={this.state.imageItemToDisplay.name}
visible={this.state.popupVisible}
onHiding={this.hideImagePopup}
className="photo-popup-content"
>
<img src={this.state.imageItemToDisplay.url} className="photo-popup-image" />
</Popup>
</div>
) : (
""
)}
</>
);
}
}
export default App;
We had the same issue lately, if I'm not mistaken, it was related to a mismatch between some DLLs versions of the project. The client-side version must match the FileSystemCommandeProcessor version. The DevExtreme team seems to have changed some property name which cause this issue.

Problem sending POST body to the Firestore REST API

I want to create a new document in Firestore using the REST API.
Very good examples here using Axios to send the POST request with some fields:
https://www.jeansnyman.com/posts/google-firestore-rest-api-examples/
axios.post(
"https://firestore.googleapis.com/v1/projects/<PROJECTIDHERE>/databases/(default)/documents/<COLLECTIONNAME>",
{
fields: {
title: { stringValue: this.title },
category: { stringValue: this.category },
post: { stringValue: this.post },
summary: { stringValue: this.description },
published: { booleanValue: this.published },
created: { timestampValue: new Date() },
modified: { timestampValue: new Date() }
}
}
).then(res => { console.log("Post created") })
And an example here using Python Requests:
Using the Firestore REST API to Update a Document Field
(this is a PATCH request but the field formatting is the same as in a POST request)
import requests
import json
endpoint = "https://firestore.googleapis.com/v1/projects/[PROJECT_ID]/databases/(default)/documents/[COLLECTION]/[DOCUMENT_ID]?currentDocument.exists=true&updateMask.fieldPaths=[FIELD_1]"
body = {
"fields" : {
"[FIELD_1]" : {
"stringValue" : "random new value"
}
}
}
data = json.dumps(body)
headers = {"Authorization": "Bearer [AUTH_TOKEN]"}
print(requests.patch(endpoint, data=data, headers=headers).json())
I am using Google Apps Script UrlFetchApp.fetch to send my requests. I am able to use GET requests with no problems. For example, to get all the documents in a collection (in Google Apps Script):
function firestore_get_documents(){
var options = {
headers: { 'Authorization': 'Bearer ' + ScriptApp.getOAuthToken() },
method:'GET'
}
var response = UrlFetchApp.fetch('https://firestore.googleapis.com/v1/projects/<PROJECTIDHERE>/databases/(default)/documents/myCollection', options);
var parsed = JSON.parse(response.getContentText());
return parsed;
}
This works nicely. And changing 'method' to 'POST' creates a new document in myCollection as expected. Then I try to add a POST body with some fields (or just one field):
function firestore_create_new_document(){
var options = {
headers: { 'Authorization': 'Bearer ' + ScriptApp.getOAuthToken() },
method:'POST',
payload: {fields: { title: { stringValue: 'newTitle' } } }, // If you comment out this line, it works as expected
muteHttpExceptions:true
}
var response = UrlFetchApp.fetch('https://firestore.googleapis.com/v1/projects/<PROJECTIDHERE>/databases/(default)/documents/myCollection', options);
var contentText = response.getContentText();
var parsed = JSON.parse(response.getContentText());
return parsed;
}
I get the following errors:
code: 400 message: "Request contains an invalid argument."
status: "INVALID_ARGUMENT"
details[0][#type]: "type.googleapis.com/google.rpc.BadRequest"
details[0][fieldViolations][0][field]: "{title={stringValue=newTitle}}"
details[0][fieldViolations][0][description]: "Error expanding 'fields' parameter. Cannot find matching fields for path '{title={stringValue=newTitle}}'."
Documentation is available here:
https://firebase.google.com/docs/firestore/reference/rest/v1/projects.databases.documents/createDocument
https://firebase.google.com/docs/firestore/reference/rest/v1/projects.databases.documents#Document
The problem may be the formatting of my 'fields' object - I've tried several different formats from the documentation and examples
The problem may be that the fields don't exist yet? I think I should be able to create a new document with new fields
The problem may be with the way UrlFetchApp.fetch sends my JSON body. I have tried using payload = JSON.stringify(payload_object) and that doesn't work either.
I think UrlFetchApp is doing something slightly different than Axios or Python Requests - the body is getting sent differently, and not parsing as expected.
How about the following modification?
From:
var options = {
headers: { 'Authorization': 'Bearer ' + ScriptApp.getOAuthToken() },
method:'POST',
payload: {fields: { title: { stringValue: 'newTitle' } } }, // If you comment out this line, it works as expected
muteHttpExceptions:true
}
To:
var options = {
headers: { 'Authorization': 'Bearer ' + ScriptApp.getOAuthToken() },
method:'POST',
payload: JSON.stringify({fields: { title: { stringValue: 'newTitle' } } }),
contentType: "application/json",
muteHttpExceptions:true
}
When I tested above modified request, I could confirm that it worked. But if other error occurs, please tell me.
Reference:
Class UrlFetchApp

File is empty in Symfony after uploading with react-native-fetch-blob

I want to upload a picture from react-native to PHP Symfony server. I pick the picture with ImagePicker.showImagePicker and send it with RNFetchBlob.fetch, but in Symfony the file seems to be empty. The $file->getMimeType() return "file does not exist or is not readable" and the content type of the file is octet-stream. It Should be image/jpeg.
Any Idea ?
Thanks for help :)
PHP code:
private function uploadFile(Request $request, $actualFilename = null)
{
$file = $request->files->get('userfile');
var_dump($file->getMimeType());
}
React-native code :
const options = {
title: 'Select Photo',
takePhotoButtonTitle: "Take photo title",
chooseFromLibraryButtonTitle: "Choose a photo",
quality: 1
};
ImagePicker.showImagePicker(options, response => {
deviceStorage.getItem('jwt').then(jwt => {
const endpoint = 'someEndpoint'
RNFetchBlob.fetch('POST', endpoint, {
Authorization : "Bearer " + jwt,
otherHeader : "foo",
'Content-Type' : 'multipart/form-data',
}, [
{ name : 'userfile', filename : 'image.jpg', type:'image/jpeg', data: response.data}
]).then((resp) => {
console.log(resp);
}).catch((err) => {
console.log(err);
});
});
});
You have passing the image data, so in the server you get a base64, to retrieve the image you will for example:
private function uploadFile(Request $request, $actualFilename = null){
$base64Image = $request->get('userfile');
$data = base64_decode($base64Image);
file_put_contents($imagePath, $data);
}
$imagePath is where you save the image.
If you use vichuploader to manage the images take a look here base64-image-to-image-file-with-symfony-and-vichuploader

Get an error from Angular2 http in Es5

I am trying to use http with Angular2.
Here is my code:
var _domain = 'http://localhost:3000/';
app.Applications = ng.core.Injectable().Class({
constructor: [ng.http.Http, function(http) {
this.http = http;
this.emailExistUrl = _domain + 'api/applications/email';
}],
doesEmailExist: function(email) {
var data = { email: email };
return this.http.post(this.emailExistUrl, data)
.toPromise()
.then(function(response) { response.json().data; })
.catch(this.handleError);
}
});
The main component:
app.AppComponent = ng.core
.Component({
selector: 'register-form',
templateUrl: 'src/register/app.component.html',
providers: [app.Applications]
})
.Class({
constructor: [ng.core.ElementRef, app.Applications, function(ref, Applications) {
this.programs = JSON.parse(ref.nativeElement.getAttribute('programs'));
this.applications = Applications;
}],
doesEmailExist: function(email) {
return this.applications.doesEmailExist(email);
}
});
Here is main.js file:
document.addEventListener('DOMContentLoaded', function() {
ng.platformBrowserDynamic.bootstrap(app.AppComponent, [
ng.forms.disableDeprecatedForms(),
ng.forms.provideForms(),
ng.http.HTTP_PROVIDERS,
]);
});
When doesEmailExist is called I get an error from the http module:
vendor-client.min.js:55470 TypeError: Cannot read property 'platform_browser_private' of undefined
Any ideas?
FIXED:
Http was before platform-browser on the script tag list. :/
<script src="https://npmcdn.com/#angular/http/bundles/http.umd.js"></script>
<script src="https://npmcdn.com/#angular/platform-browser/bundles/platform-browser.umd.js"></script>
<script src="https://npmcdn.com/#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script>
The inverse is better :)
Try to assign http at the beginning of the constructor:
app.Applications = ng.core.Injectable().Class({
constructor: [ng.http.Http, function(http) {
this.http = http;
...
}],
doesEmailExist: function(email) {
...
}
});
EDIT
See this Plunker: http://plnkr.co/edit/aQWqxauklT7MqSjfhLFD. To simplify, I have put everything in main.js file, and instead of an http post I have implemented an http get. However, locally, even the http post works with a web service API. I hope it's helpful to solve your problem.

Resources