From Salesforce File, I want to read the file and get the content between some text and store it in the Custom object record field.
For this, I have created an external API(python script deployed to heroku) where I am sending the file content as blob(basically the content of the file is Blob in Salesforce
).
Now I want to read the file and get the text. But I was not able to read the blob data.
If I convert the blob to string in SF while posting and decode it in python also doesn't work. Please give some inputs on this. I am new to python.
my python code :
from flask import Flask, request, jsonify
import base64
import blob
app = Flask(__name__)
#app.route('/get/record/', methods=['GET', 'POST','DELETE', 'PATCH'])
def index():
if request.method == 'POST':
print("===inside===")
payload_list = request.get_json(force=True)
print("====next line payload_list ===")
print(blob(payload_list["BlobData"])
# responseStr = str(payload_list["BlobData"])
# print("===decodedata===")
# print(base64.b64decode(responseStr))
return "sucesss"
Salesforce Rest Code:
List<ContentVersion> cv = [SELECT ContentDocumentId,VersionData from ContentVersion
where ContentDocumentId = 'xxxxxxxxxx' order by CreatedDate DESC];
String bodyEncoded = EncodingUtil.base64Encode(cv[0].versiondata);
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint('https://realpyth.herokuapp.com/get/fileService/');
request.setMethod('POST');
request.setHeader('Content-Type', 'application/json');
request.setBody('{"BlobData":"'+cv[0].versiondata+'"}'); // Send the data as Blob
//request.setBody('{"BlobData":"'+bodyEncoded+'"}'); // Convert the blob data and send as String
HttpResponse response = http.send(request);
if (response.getStatusCode() != 201) {
System.debug('=======' +response.getStatusCode() + ' ' + response.getBody());
} else {
System.debug('====response==='+response.getBody());
}
Related
I am trying to pass the path of an xml file to a flask/Python based REST-microservice. When passing the url manually to the service, it works as intended. However, I have problems calling the service from my laravel project.
Call to python rest service from laravel:
function gpxToJson(){
url = "http://127.0.0.1:5000/convert?path=C:/xampp/htdocs/greenlaneAdventures/public/storage/gpx/OOCe4r5Mas8w94uGgEb8qYlI0T3ClZDoclcfrR7s.xml" ;
fetch(url).then(function (response){
var track = JSON.parse(response.json());
return track;
});
}
Python script:
import gpxpy
import pandas as pd
from flask_cors import CORS
from flask import Flask, request, make_response, render_template
from flask_restful import Resource, Api
# create empty web-application
app = Flask(__name__)
api = Api(app)
CORS(app)
# create necessary classes
class Converter(Resource):
def get(self):
# path passed as argument
file = request.args.get('path', '')
# parse gpx file
gpx = gpxpy.parse(open(file))
# define data
track = gpx.tracks[0]
segment = track.segments[0]
# load wanted data into a panda dataframe
data = []
segment_length = segment.length_3d()
for point_idx, point in enumerate(segment.points):
data.append([point.longitude, point.latitude, point.elevation,
point.time, segment.get_speed(point_idx)])
columns = ['Longitude', 'Latitude', 'Altitude', 'Time', 'Speed']
gpx_df = pd.DataFrame(data, columns=columns)
# convert dataframe to json
gpx_json = gpx_df.to_json(orient='index')
print(gpx_json)
#return the converted json (http response code 200 = OK. The request has suceeded)
headers = {"Content-Type": "application/json"}
return make_response(gpx_json, 200, headers)
api.add_resource(Converter, "/convert")
#error handling
#app.errorhandler(404)
def not_found():
"""Page not found."""
return make_response(
render_template("404.html"),
404
)
#app.errorhandler(400)
def bad_request():
"""Bad request."""
return make_response(
render_template("400.html"),
400
)
#app.errorhandler(500)
def server_error():
"""Internal server error."""
return make_response(
render_template("500.html"),
500
)
#main function call
if __name__ == "__main__":
app.run(debug=True)
When calling the function gpxToJson() by submitting a form, I get the following error message in firefox.
I am trying to send a POST request to my Python Flask Server. I tried to send a CSV file using the form-data option of POSTMAN. It was successfully received by the Flask server.
Now, I want to send a JSON payload along with the CSV file which will consist of the User credentials.
I tried the below method but it does not seem to be working. Although, I am receiving the CSV file but the JSON is still not received by the Flask server.
class Upload_File(Resource):
def post(self):
file_ = request.files['file']
Q_data = pd.read_csv(file_, header=None, names=['Questions'])
print(Q_data) # successfully displays file content
data = request.get_json(force=True) # gives None
EDIT
The issue was with the Flask code. The working code is -
class Upload_File(Resource):
def post(self):
file_ = request.files['file']
Q_data = pd.read_csv(file_, header=None, names=['Questions'])
print(Q_data) # successfully displays file content
username = request.form.get('username') # modified
password = request.form.get('password') # modified
The request is parsed as Form data. So, you need to check whether you can get it via request.post dictionary.
Example:
class Upload_File(Resource):
def post(self):
file_ = request.files['file']
Q_data = pd.read_csv(file_, header=None, names=['Questions'])
print(Q_data) # successfully displays file content
data = request.post['admin']
I have an endpoint which is receiving a text file from a request, which the flask server processes and now need to send a response which should be a json file. I have read and performed the operations of received txt file, and now when I send the dict by jsonify I get this in terminal.
Response 444 bytes [200 OK]
How do I get the json file or is there any other way of sending the JSON file in response? Since I won't be in control of the server that will send the request I need a way to send JSON file.
Code Handling the response
#app.route('/automated_testing', methods=['GET','POST'])
def getfile():
if request.method == 'POST':
for file in request.files:
links = request.files[file].read()
#Since a byte sized object is returned
links = [links.decode('utf8').strip()]
links = links[0].split("\n")
res = dict()
for i in links:
f = FlarePredictor(i)
res[i] = f[0]
print(jsonify(res), file=sys.stderr)
return jsonify(res)
else:
return "GET REQ"
return "Hi"
Code used to send the request
import requests
with open('test.txt', 'rb') as f:
r = requests.post('http://127.0.0.1:5000/automated_testing', files={'test.txt': f})
requests supports JSON out-of-the-box:
json = r.json()
Now json will be a regular Python dictionary containing the data.
I am stuck in a problem where I am trying to build single API which will upload file along with json object. I need this API to create webhook.
Using multi part, I am able to upload file and in option filed I am able to send json object.
In flask app when I am trying to retrieve json object its converting as blob type. I tried to convert it base64 then again converting into string but whole process is not working.
Let me know if anyone has good solution I can combine file and json object together and fetch it by flask python app.
zz is the variable in my code where I am trying to store my json object. name is the field where I am passing my json object with file.
Thanks in advance.
My current code
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route('/upload/',methods = ['POST'])
def upload():
customer_name='abc'
if request.method == 'POST':
zz=base64.b64encode(request.files['name'].read())
try:
file = request.files['file']
if file:
file.filename=customer_name+'_'+str(datetime.now())+'.'+file.filename.split('.')[-1]
filename = secure_filename(file.filename)
path=os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(path)
return jsonify({
'status':success,
'junk_data':[],
'message':error
})
except Exception as err:
logger.error(str(datetime.now())+' '+str(err))
return jsonify({
'status':False,
'junk_data':[],
'message':str(err)
})
if __name__ == '__main__':
app.run(host='localhost',debug=True, use_reloader=True,port=5000)
I have got the answer after lot R&D.
request format
//user any client-side
content-type:multipart/form-data
file: file need to upload
data: {"name":"abc","new_val":1}
python code to fetch from request object
data=json.loads(request.form.get('data'))
file = request.files['file']
Just send the file and json at once and let request handle the rest.
You can try the code below:
Server side:
import json
import os
from flask import Flask, request
from werkzeug import secure_filename
app = Flask(__name__)
#app.route('/test_api',methods=['GET','POST'])
def test_api():
uploaded_file = request.files['document']
data = json.load(request.files['data'])
filename = secure_filename(uploaded_file.filename)
uploaded_file.save(os.path.join('path/where/to/save', filename))
print(data)
return 'success'
if __name__ == '__main__':
app.run(host='localhost', port=8080)
Client Side:
import json
import requests
data = {'test1':1, 'test2':2}
filename = 'test.txt'
with open(filename, 'w') as f:
f.write('this is a test file\n')
url = "http://localhost:8080/test_api"
files = [
('document', (filename, open(filename, 'rb'), 'application/octet')),
('data', ('data', json.dumps(data), 'application/json')),
]
r = requests.post(url, files=files)
print(r)
At Server end I use Python flask:
from flask import Flask, request
app = Flask(__name__)
#app.route("/upload", methods=["POST"])
def upload():
print request.files
print request.form
return "200 ok"
if __name__ == '__main__':
app.run(port=5000)
Java test code block:
public void test_Upload() throws Exception{
MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
MediaType MEDIA_TYPE_XO = MediaType.parse("image/png");
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"title\""),
RequestBody.create(null, "Square Logo"))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"image\""),
RequestBody.create(MEDIA_TYPE_PNG, new File("/Users/lollipop/Downloads/ic_launch.png")))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"google\""),
RequestBody.create(MEDIA_TYPE_XO, new File("/Users/lollipop/Downloads/google-logo.png")))
.build();
Request request = new Request.Builder()
.url("http://localhost:5000/upload")
.post(requestBody)
.build();
Response resp = httpClient.newCall(request).execute();
System.out.println(resp.body().string());
}
And I run the test. server end cannot read the file from request.forms
output on server:
ImmutableMultiDict([])
ImmutableMultiDict([('image', u'5 ...many data ... fffd'), ('google', u'5i\u ...many data ... fffd'),('title', u'Square Logo')])
Why my files upload to request.form not in request.files. And all binary file data is parsed to unicode string.
Next, I test in Python requests. follows codes:
resp = requests.post("http://localhost:5000/upload",
files={
"image": open("/Users/lollipop/Downloads/ic_launch.png", "rb"),
"title": open("/Users/lollipop/Downloads/ic_launch.png", "rb"),
"google": open("/Users/lollipop/Downloads/google-logo.png", "rb")
})
And the server end output is reversed:
ImmutableMultiDict([('image', <FileStorage: u'ic_launch.png' (None)>), ('google', <FileStorage: u'google-logo.png' (None)>), ('title', <FileStorage: u'ic_launch.png' (None)>)])
ImmutableMultiDict([])
the upload files are in request.files not in request.form, this is my expected result.
So. how can I use OkHttp to upload files to flask server, and use request.files to retrive.
Update
the request is Flask requst.
from flask import request
the requests is a Python http client library.
This bug is not to Flask. I get misguided by this answer
At the OkHttp recipe in the documents. Described the post a file use the following code
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
File file = new File("README.md");
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
Actually, this manner is not error, it post a file you don't need to provide a filename and other form data.
But this is not a usual usage.
We often need to upload a file with specified name and some key-value form data. We even need to upload more than one file.
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addFormDataPart("username", username)
.addFormDataPart("password", password)
.addFormDataPart("avatar", "avatar.png", RequestBody.create(MEDIA_TYPE_PNG, sourceFile))
.addFormDataPart("introduce_image", "introduce_image.png", RequestBody.create(MEDIA_TYPE_PNG, sourceFile))
.build();