flask & reactjs file uploading not working - javascript

I'm new to python flask, I'm using flask in backend and react js in front end and pymongo for the database. I want to upload the file from ReactJs to the flask server, I 'm getting an error while doing second method, How can I do it. Below is the code that I have tried.
I had tried two examples one is working and the other is not I don't know why.
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'file'
Directly sending the file to API. Case 1
Python code
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = set([ 'png', 'jpg', 'jpeg'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route('/api/users/add_photo', methods=['POST', "GET"])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
image = upload(open(filename, 'rb'))
user_id = user.insert({"file":image})
return jsonify({'result': "file Upload successfully!!!"})
onSubmitImage(e) {
let file = this.state.file;
let formData = new FormData();
formData.append("file", file);
this.props.imageUpload(formData);
}
Above example is working perfectly
Sending a file to API in the object. Case 2
Python code
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = set([ 'png', 'jpg', 'jpeg'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route('/api/users/add_photo', methods=['POST', "GET"])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
name = request.get_json(force=True)["name"]
last_name = request.get_json(force=True)["last_name"]
email = request.get_json(force=True)["email"]
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
image = upload(open(filename, 'rb'))
user_id = user.insert({"file":image,"name":name,"last_name":last_name,"email":email})
return jsonify({'result': "file Upload successfully!!!"})
onSubmitImage(e) {
let file = this.state.file;
let formData = new FormData();
formData.append("file", file);
const data = {
file: formData
name: this.state.name
last_name: this.state.last_name
email: this.state.last_name
};
this.props.imageUpload(data);
}
I don't know why first is working and second not. I want to implement the second example because there other are data like name, last_name, email with image file.

You need to add your data to your FormData()- ie
let file = this.state.file;
let formData = new FormData();
formData.append("file", file);
formData.append("name", this.state.name);
formData.append("last_name", this.state.last_name)
formData.append("email", this.state.last_name)
this.props.imageUpload(formData);

Related

How to send docx file in bytes to frontend in Django?

I read the file in Django side as a python file:
with open("file.docx", mode="rb") as f:
bytes = f.read()
and I send it:
from django.http import FileResponse
return FileResponse(bytes)
In javascript I use this function:
function downloadBuffer(arrayBuffer, fileName) {
const a = document.createElement('a')
a.href = URL.createObjectURL(new Blob(
[ arrayBuffer ],
{ type: 'aapplication/vnd.openxmlformats-officedocument.wordprocessingml.document' }
))
a.download = fileName
a.click()
}
However the file is corrupted. How can I get the file correctly?

Facing an issue about populating the javascript array

I have been working on a project which is to create a node.js server and I have to read some text from the file. Then I want to use a Python API to consume these text and get the result back. I have been able to hit these API and get the response successfully.
What have I done till now -
1. Created a node server
2. read all the file and get the text content from them
3. create a flask server with appropriate api
4. hit these API to get the response
app.js
var bodyParser = require('body-parser');
var request = require('request-promise');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.get('/', function(req, res){
res.send('Node server')
})
app.get('/postdatatoFlask', function (req, res) {
var fs = require('fs');
categories = ['business', 'entertainment']
// answers SHOULD CONTAIN ALL THE RESPONSES FROM THE FLASK API
var answers = []
//iterating over different file
categories.forEach(function(category){
for(var i=100;i<=100;i++){
//creating the path for the new file to be read
var path = 'dataset/'+category+'/'+i.toString()+'.txt';
//textContent contains the data read from file
var textContent = fs.readFileSync(path, 'utf8')
//creating the object
var data = { content : textContent }
//posting the data to the flask server on route postdata
var options = {
method: 'POST',
uri: 'http://127.0.0.1:5000/postdata',
body: data,
json: true
};
// returndata is the variable contains the data return by flask API
var returndata
var sendrequest = request(options)
.then(function (parsedBody) {
// parsedBody contains the data sent back from the Flask server
returndata = parsedBody;
answers.push(returndata)
console.log(returndata) // do something with this data, here I'm assigning it to a variable.
})
.catch(function (err) {
console.log(err);
});
}
})
console.log('Showing the responses!!!')
console.log(answers)
console.log('Stoping the showcase!!!!')
res.send('done');
});
app.listen(3000);
compute.py
import json
import time
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from io import StringIO
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
import pandas as pd
app = Flask(__name__)
#app.route('/')
def index():
return "Flask server"
#app.route('/postdata', methods = ['POST'])
def postdata():
data = request.get_json()
# print(data['content'])
textContent = data['content']
print(textContent)
print('-- --- -- --- -- -- -- -- -- --')
return json.dumps({"newdata":textContent})
if __name__ == "__main__":
app.run(port=5000)
Problem
1. In app.js I want to store all the responses in answer array but I am unable to populate it.
2. why output from console.log(returndata) print after console.log(answer)
With answers.push(returndata), you are pushing an array inside another array. If you want to concat the content of returndata to answers, use answers.push(...returndata)
Javascript has an async, non blocking IO runtime, so here:
var sendrequest = request(options)
.then(function (parsedBody) {
// parsedBody contains the data sent back from the Flask server
returndata = parsedBody;
answers.push(returndata)
console.log(returndata) // do something with this data, here I'm assigning it to a variable.
})
The callback inside then is put to the callstack after those:
console.log('Showing the responses!!!')
console.log(answers)
console.log('Stoping the showcase!!!!')
var options = {
method: 'POST',
uri: 'http://127.0.0.1:5000/postdata',
body: data,
json: true
};
// returndata is the variable contains the data return by flask API
try {
// temp.push(await request(options));
answers.push(await request(options));
} catch(err) {
throw err;
}

Upload files with telegram bot - NodeJS

I want to upload a .txt file to telegram with my javascript bot.
I've seen a few examples in php and python but didn't understand, so I just need a js example to find out.
Should I upload a file first and then sendDocmuent or should input in sendDocmuent?
I've tried sendDocument with document: 'file.txt' but didn't work.
Also read about form-data but got nothing!
call("sendDocument",{
chat_id: owner,
document: 'file.txt' // or /file.txt or full address (C:...)
});
I'm not using any library, here is my call function:
const botUrl = "https://api.telegram.org/bot" + token + "/";
const request = require('request');
function call(method, params, onResponse)
{
var requestData = params;
var data = {
url: botUrl+method,
json: true,
body: requestData
};
request.post(data, function(error, httpResponse, body){
if (onResponse) {
if(body)
{
onResponse(body.result);
}
}
});
}
Telegram bot API
EDITED: This is the code that works for me.
It seems that what the Telegram API never requires a file name for the sendDocument method:
File to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data
Instead of just sending out the string 'file.txt', you need to actually send the contents of the file, as a multipart/form-data, as you had guessed. Building on this answer, you just need to modify the form field of the request object:
const request = require('request')
const fs = require('fs')
const token = '752511654:AAGnu88dyi7YsmpZfcaA6XvR26Fy7f2moGo'
const url = 'https://api.telegram.org/bot'+token+'/sendDocument'
const chat_id = "741718736"
let r = request(url, (err, res, body) => {
if(err) console.log(err)
console.log(body)
})
let f = r.form()
f.append('chat_id', chat_id)
f.append('document', fs.createReadStream('file.txt'))

Bot Framework : Error while creating a csv file in Node Js

I'm developing a chatbot using Microsoft Bot Framework with Node Js.
My purpose is to send the user a csv file while he asks me something.
I've implemented the following function but while I download the file 'prova.csv' the format is not recognized.
Inspecting well the format in output is of the type: "data"
Anyone can help me what's wrong? Thanks
function (session, results, next) {
if (results.response.entity === 'Si') {
const contentType = 'text/csv';
const response = session.dialogData.far_ric_formato.response.rows;
const csv = response.map(ric => `${ric.num};${ric.pin}`).join('\n');
session.send({
text: 'Ecco il CSV pronto per il download (MOCK)',
attachments: [
{
contentType: contentType,
contentUrl: `data:${contentType};base64,${Buffer.from(csv).toString('base64')}`,
name: 'prova.csv'
}
]
});
Base64 string of a .csv file can't be directly rendered on client side, as a workaround you can for example code like this:
var restify = require('restify');
var fs = require('fs');
bot.dialog('download', (session, result)=>{
fs.readFile('./files/test.csv', function(err, data){
var contentType = 'text/csv';
var base64 = Buffer.from(data).toString('base64');
var msg = new builder.Message(session)
.addAttachment({
contentUrl: 'http://localhost:3978/csv/'+base64, //replace with your server url + base64 string.
contentType: contentType,
name: 'MyTest.csv',
});
session.send(msg);
});
}).triggerAction({matches:/^download/i});
server.get('/csv/:base64code', (req, res, next)=>{
let base64code = req.params.base64code;
res.header('Content-disposition', 'inline; filename=test.csv');
res.header('Content-type', 'application/csv');
res.send(Buffer.from(base64code, 'base64'));
});
When user trigger the download dialog, it will send this file as attachment and when user click on this file, this .csv file will be downloaded in user's client side.

Use google drive api to store appdata

I am trying to store a json object that contains config info in a Google Drive Appdata file. I am currently writing the app in JS that is run on the client side. Using the Google Drive API, I can currently check for the file in the appdata folder. How would I go about generating a new file and storing it in the appdata folder if the config was not found?
var request = gapi.client.drive.files.list({
'q': '\'appdata\' in parents'
});
request.execute(function(resp) {
for (i in resp.items) {
if(resp.items[i].title == FILENAME) {
fileId = resp.items[i].id;
readFile(); //Function to read file
return;
}
}
//Create the new file if not found
});
The gapi client does not provide a method to upload files to google drive (it does for metadata) but they do still expose an API endpoint.
Here's an example I've been using for the V3 api
function saveFile(file, fileName, callback) {
var file = new Blob([JSON.stringify(file)], {type: 'application/json'});
var metadata = {
'name': fileName, // Filename at Google Drive
'mimeType': 'application/json', // mimeType at Google Drive
'parents': ['appDataFolder'], // Folder ID at Google Drive
};
var accessToken = gapi.auth.getToken().access_token; // Here gapi is used for retrieving the access token.
var form = new FormData();
form.append('metadata', new Blob([JSON.stringify(metadata)], {type: 'application/json'}));
form.append('file', file);
var xhr = new XMLHttpRequest();
xhr.open('post', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id');
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xhr.responseType = 'json';
xhr.onload = () => {
console.log(xhr.response.id); // Retrieve uploaded file ID.
callback(xhr.response);
};
xhr.send(form);
}
And since google drive will allow duplicate filenames since they're unique by ID I use something like this to check if it exists already:
function fileExists(file, fileName){
var request = gapi.client.drive.files.list({
spaces: 'appDataFolder',
fields: 'files(id, name, modifiedTime)'
});
request.execute(function(res){
var exists = res.files.filter(function(f){
return f.name.toLowerCase() === fileName.toLowerCase();
}).length > 0;
if(!exists){
saveFile(file, fileName, function(newFileId){
//Do something with the result
})
}
})
}
Check the documentation about Storing Application Data:
The 'Application Data folder' is a special folder that is only accessible by your application. Its content is hidden from the user, and from other apps. Despite being hidden from the user, the Application Data folder is stored on the user's Drive and therefore uses the user's Drive storage quota. The Application Data folder can be used to store configuration files, saved games data, or any other types of files that the user should not directly interact with.
NOTE:
To be able to use your Application Data folder, request access to the following scope:
https://www.googleapis.com/auth/drive.appdata
If you'll check the sample code on how to insert a file into the Application Data folder(PHP code):
$fileMetadata = new Google_Service_Drive_DriveFile(array(
'name' => 'config.json',
'parents' => array('appDataFolder')
));
$content = file_get_contents('files/config.json');
$file = $driveService->files->create($fileMetadata, array(
'data' => $content,
'mimeType' => 'application/json',
'uploadType' => 'multipart',
'fields' => 'id'));
printf("File ID: %s\n", $file->id);
By adding appDataFolder as a parent for the file will make it write to the appFolder. Then implement you own uploading/cody code to insert the file and its content to the appFolder.
Hope this helps

Categories

Resources