Flutter multipart/form-data send list of items - arrays

My using package http
I have this method in my app to send post request with files. In my case I send files and also fields with dynamic values. I tried send List<String> but server (backend) return me error with message:
The seedlings field must be an array.
Example seedlings list value:
List<String> seedlings = ['Apple', 'Banana'];
Code:
Future post(String path, data) async {
await _getToken();
var url = '${ApiConstants.BASE_URL}$path';
var uri = Uri.parse(url);
var request = MultipartRequest('POST', uri);
data.forEach((key, item) async {
if (item == null) return null;
if (item is File) {
request.files.add(await MultipartFile.fromPath(
'file',
item.path,
));
} else {
request.fields[key] = item is num
? item.toString()
: item is List
? item.toString()
: item;
}
});
request.headers['Content-type'] = 'application/json';
request.headers['Accept'] = 'application/json';
var response = await request.send();
}
In my case all fields sent to server except fields with list of values like array

This might be old, but you can easily do this by adding the array items into a form data array
final FormData formData = FormData({});
// Add all normal string request body data
formData.fields.add(MapEntry("name", "Olayemii"));
formData.fields.add(MapEntry("age", 99));
// Add all files request body data
formData.files.add(MapEntry("profile_photo", file));
// Add the array item
List<String> seedlings = ['Apple', 'Banana'];
seedlings.forEach((element) {
formData.fields.add(MapEntry("seedlings[]", element.toString()));
});

I have found an answer for this which I have posted in another similar question. I'll just put the code snippet here.
final request = http.MultipartRequest('Post', uri);
List<String> ManageTagModel = ['xx', 'yy', 'zz'];
for (String item in ManageTagModel) {
request.files.add(http.MultipartFile.fromString('manage_tag_model', item));
}
Basically you have to add the list as files with fromString() method.
Find the original answer here-
https://stackoverflow.com/a/66318541/7337717

Related

HTTPS Post URL with an Array of Objects

I've been trying to format a URL POST with objects in my array as they're required to post to my REST API. I'm forced to use an archaic API POST system from a vendor and have been trying to hack together a solution.
Basically the JSON looks similar to:
{"api_key": "12234",
"server_id:"qwp2222",
"recipients": [
{"email":"john#doe.com",
"name": "john doe"}]
}
I am trying to format the Array'd key-value pairs as part of the URL so it would post to the endpoint without much fanfare.
I have the rest of the URL together without issue, it is just the recipients' array that is the problem.
How should I write the POST URL in order to make sure that I can post the array of objects correctly?
I appreciate all the help in advance!
Does not work here, but this code will make linear structure from your JSON, create form from and submit to itself.
If you run it on local or anywhere else and add f.action = 'your get or post page', it will send data properly.
var data = {
api_key: '12234',
server_id: 'qwp2222',
recipients: [{
email: 'john#doe.com',
name: 'john doe'
}]
};
function collectItems(res, json) {
for (var a in json) {
if (json[a].constructor === Array ||
json[a].constructor === Object) {
collectItems(res, json[a]);
} else {
res.push([a, json[a]]);
}
}
}
var all = [];
collectItems(all, data);
var f = document.createElement('FORM');
f.method = 'post';
// default get: ...?api_key=12234&server_id=qwp2222&email=john#doe.com&name=john+doe
for (var e in all) {
var i = document.createElement('INPUT');
i.name = all[e][0];
i.value = all[e][1];
i.type = 'hidden'; // do not show values sent
f.appendChild(i);
}
if (location.search) {
alert("Submit result:" & location.href);
} else {
document.body.appendChild(f);
f.submit();
}

How to parse this JSON Array in Flutter?

I am working with Flutter and am currently trying to create a graph. I am looking to parse this JSON Array from the link below. My issue is that the information provided in the "prices" object, the values are all inside arrays themselves. I want to get those values and split them into an X and Y list but I have no idea how to accomplish this. I posted a snippet of the JSON data below.
https://api.coingecko.com/api/v3/coins/bitcoin/market_chartvs_currency=usd&days=1
I am only familiar with parsing data by creating a class and constructor. Then create a fromJSON(Map<String, dynamic> json) class and putting the data into a list, as shown in the code snippet below that I created from another URL with object values. How could I go about parsing this array JSON data into two list data?
CODE TO PARSE JSON
List<Coins> _coins = List<Coins>();
Future<List<Coins>> fetchCoins() async {
var url = 'URL';
var response = await http.get(url);
var coins = List<Coins>();
if (response.statusCode == 200) {
var coinsJSON = json.decode(response.body);
for (var coinJSON in coinsJSON) {
coins.add(Coins.fromJson(coinJSON));
}
}
return coins;
}
#override
void initState() {
fetchCoins().then((value) {
setState(() {
_coins.addAll(value);
});
});
super.initState();
}
class Coins{
String symbol;
String name;
Coins(this.symbol, this.name);
Coins.fromJson(Map<String, dynamic> json) {
symbol = json['symbol'];
name = json['name'];
JSON DATA SNIPPET
{
"prices":[
[
1566344769277,
10758.856131083012
],
[
1566345110646,
10747.91694691537
],
[
1566345345922,
10743.789313302059
],
]
}
EDIT: SOLVED WITH THE HELP OF #EJABU.
class HistoricalData {
List prices;
List<num> listX = [];
List<num> listY = [];
HistoricalData(this.prices,this.listX, this.listY);
HistoricalData.fromJson(Map<String, dynamic> json) {
prices = json['prices'];
for (var price in prices) {
listX.add(price[0]);
listY.add(price[1]);
}
}
You may try this...
New class Coins definition:
class Coins {
List<num> listX = [];
List<num> listY = [];
Coins(this.listX, this.listY);
Coins.fromJson(Map<String, dynamic> json) {
List<List<num>> prices = json['prices'];
for (var price in prices) {
listX.add(price[0]);
listY.add(price[1]);
}
}
}
Then later you can fetch it by these lines :
// Future<List<Coins>> fetchCoins() async { // Remove This
Future<Coins> fetchCoins() async {
var url = 'URL';
var response = await http.get(url);
// var coins = List<Coins>(); // Remove This
Coins coins;
if (response.statusCode == 200) {
var coinsJSON = json.decode(response.body);
// Remove This
// for (var coinJSON in coinsJSON) {
// coins.add(Coins.fromJson(coinJSON));
// }
//
coins = Coins.fromJSON(coinsJSON);
}
return coins;
}
Accessing Data in Widget
In Widgets , our expected variable resides as property inside Coins class.
For example, if you use FutureBuilder, you may use these lines:
child: FutureBuilder(
future: fetchCoins(),
builder: (_, __) {
return SomeChartWidget(
listX: coins.listX,
listY: coins.listY,
);
},
),
Generating Serializers automatically
I suggest you take a look at https://pub.dev/packages/json_serializable, which is a package that does the boilerplate code generation for you. Although it might me a bit overkill to add something like this to your code or your workflow, automatically generating serializers is very convenient.
Not that in order to have custom sub-classes, they need to provide serialization as well.
If you want to extend your knowledge even further, you can also have a look at https://pub.dev/packages/built_value and https://pub.dev/packages/built_value_generator

How to delete an element from google datastore as well as my html page using delete method?

Iam currently using flask and google datastore and working on it
#app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['DELETE'])
def delete_task(task_id):
pass
return jsonify({'result': True})
Ive used get and post and also put method for inserting retrieving and updating now i need to delete using delete request
I tried to pass the respective id value by using href in my html page but I found it doesnt work that way !
def delete_method(task_id):
k = ndb.Key('ToDo', task_id)
k.delete()
return jsonify({"success":True})
The above code works fine and the ajax request is as follows
function delData(){
var id = this.id
//console.log(id)
var url = '/DELETE/todo/api/v1.0/task/';
var xhr = new XMLHttpRequest();
xhr.open("DELETE", url+id, true);
xhr.onload = function () {
var jsonResponse = JSON.parse(xhr.responseText);
if (xhr.readyState == 4 && xhr.status == "200") {
console.log(jsonResponse);
var elem = document.getElementById(id).parentNode;
while (elem.firstChild) {
elem.removeChild(elem.firstChild);
}
}
else {
console.error(jsonResponse);
}
}
xhr.send(null);
}

Get an image of a vbhtml view as a byte array and save it to an oracle database

I need help on an mvc application in vb.net. In general terms I need to receive an image through the view and get it to work on the controller. I need to do this to convert the image to a byte array and save it to an oracle database. So my idea is to get the image and in the controller to convert it to a byte array or maybe there is some way to get the image already as a byte array and pass that array to the controller to save it to the database.
something like this its my View :
<div class="span11">
<div class="span4" id="depnac">
#Html.LabelFor(Function(m) m.DepNacPER)
#Html.DropDownListFor(Function(m) m.DepNacPER, Model.DepNacPER, New With {.class = "form-control"})
</div>
and this is my Model :
<Display(Name:="Region of birth")>
<Required(ErrorMessage:="you must select a option")>
Property DepNacPER As SelectList
I'm working on an ASP.NET Core app right now that uploads images. The image comes through to the controller via the request as a Stream. I'm then creating an Image object from that Stream but you could just read the data from it directly. That said, you might want to try to create an Image object to confirm that the data does represent a valid image.
Here's some relevant code from the view's script:
function uploadImage()
{
// This is a file upload control in a hidden div.
var image = $("#imageFile");
if (image[0].files.length > 0)
{
var formData = new FormData();
formData.append(image[0].files[0].name, image[0].files[0]);
var xhr = new XMLHttpRequest();
xhr.open("POST", "#Url.Content("~/events/uploadimage")");
xhr.send(formData);
xhr.onreadystatechange = function ()
{
if (xhr.readyState === 4 && xhr.status === 200)
{
var response = JSON.parse(xhr.responseText);
if (response.saveSuccessful)
{
// ...
} else
{
window.location.replace("#Url.Content("~/error")");
}
}
}
xhr.onerror = function(err, result)
{
alert("Error: " + err.responseText);
}
}
}
I'm in the process of replacing that code with some jQuery that does the heavy lifting but haven't got that far yet.
Here's some relevant code from the action:
[HttpPost]
public IActionResult UploadImage()
{
var requestForm = Request.Form;
StringValues tempImageFileNames;
string tempImageFileName = null;
string imageUrl = null;
var saveSuccessful = true;
var requestFiles = requestForm.Files;
if (requestFiles.Count > 0)
{
// A file has been uploaded.
var file = requestFiles[0];
using (var stream = file.OpenReadStream())
{
try
{
using (var originalImage = System.Drawing.Image.FromStream(stream))
{
// Do whatever you like with the Image here.
}
}
catch (Exception)
{
saveSuccessful = false;
}
}
}
if (saveSuccessful)
{
return Json(new {saveSuccessful, tempImageFileName, imageUrl});
}
else
{
return Json(new {saveSuccessful});
}
}
Sorry, it didn't occur to me at first that you're after VB code and this is C#. Hopefully you can still get the idea and I'll take the hit if someone dislikes the answer.

Uploading CustomData with ng-file-upload and WebApi

I am trying to upload a file along with some metadata to a WebApi Service that I have created with ng-file-upload and Angular. I am getting the file name and bytes as expected, but I am not able to get the metadata I am passing as well. Here is what I am doing on the Angular side
Upload.upload({
url: '/api/FileStorage/AddContent' + location.search,
data: {file: files, year: vm.year }
})
And the WebApi side
var streamProvider = new CustomMultipartFileStreamProvider();
IEnumerable<HttpContent> parts = null;
Task.Factory
.StartNew(() => parts = Request.Content.ReadAsMultipartAsync(streamProvider).Result.Contents,
CancellationToken.None,
TaskCreationOptions.LongRunning, // guarantees separate thread
TaskScheduler.Default)
.Wait();
var customData = streamProvider.CustomData;
Here I am using a MultiStreamProvider to get the file, here is the meat of that provider
public override Task ExecutePostProcessingAsync()
{
foreach (var file in Contents)
{
var parameters = file.Headers.ContentDisposition.Parameters;
var filename = GetNameHeaderValue(parameters, "filename");
var year = GetNameHeaderValue(parameters, "year");
}
return base.ExecutePostProcessingAsync();
}
I am able to get filename without issue, but am never able to get the year. Here is the value in the debugger when I am looking at the parameters variable
As you can see, the name is "name" and the value is "year" when I would expect the name to be "year" and value to be "2016" or whatever I am passing in. What am I doing wrong here and how do I get the metadata included in the same call to the Api?
We use a similar approach with ng-file-upload and WebAPI. To get the values out of the form data, we weren't able to use GetNameHeaderValue. We had to do some manual parsing. We decided to use modified version of what was posted at http://conficient.wordpress.com/2013/07/22/async-file-uploads-with-mvc-webapi-and-bootstrap/ to dynamically take a form and unload it to a strongly-typed Model. But basically, here's what it does in the ExecutePostProcessingAsync method:
public override async Task ExecutePostProcessingAsync()
{
var formData = new FormCollection();
for (int index = 0; index < Contents.Count; index++)
{
ContentDispositionHeaderValue contentDisposition = headers.ContentDisposition;
if (contentDisposition != null)
{
HttpContent formContent = Contents[index];
string formFieldName = UnquoteToken(contentDisposition.Name) ?? String.Empty;
// Read the contents as string data and add to form data
string formFieldValue = await formContent.ReadAsStringAsync();
formData.Add(formFieldName, formFieldValue);
}
//For your case
var filename = formData["filename"];
var year = formData["year"];
This is the UnquoteToken method this uses:
private static string UnquoteToken(string token)
{
if (String.IsNullOrWhiteSpace(token))
{
return token;
}
if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1)
{
return token.Substring(1, token.Length - 2);
}
return token;
}

Resources