bala4901
(Markus Bala)
November 30, 2020, 12:49pm
1
Hi,
I am trying to add attachment/picture to ir.attachment to json_rpc.
At first, I am using Flutter/Dart as client side.
Firstly, using base64Encode to encode the bytes to string.
String value = base64Encode(byte);
vlist = {
"data": "{'__class__': 'bytes', 'base64':" + value + "}"
}
using json_rpc, create method.
When passing to server, I get this error:
Unicode-objects must be encoded before hashing
May I know what is wrong ? and what object should pass to attachment data?
German
(German Dario Alvarez)
November 30, 2020, 6:00pm
2
Using flask_tryton I was able to add an attachment just reading the file with ‘rb’ and passing the binary data of the file.
Have you tried that ?
bala4901
(Markus Bala)
November 30, 2020, 6:13pm
3
Hi german,
Thank you, are you able to show me some example from your code?
German
(German Dario Alvarez)
November 30, 2020, 8:08pm
4
I did inside tryton module like this:
I’m sure from josn-rpc should be very similar
Attachment = Pool().get('ir.attachment')
with open('my_file', "rb") as f:
data= f.read()
attach, = Attachment.create([{'create_uid': 1, 'resource':str(invoice),'name': 'my_fname','data':data},])
Hope it helps
ced
(Cédric Krier)
November 30, 2020, 11:41pm
5
It is strange to name this vlist
when it is just a dictionary.
I guess it will be good to show exactly the RPC call you are doing.
bala4901
(Markus Bala)
December 1, 2020, 1:24am
6
Hi @ced ,
Below is my code, please help
File f = File(el.imageFile.path);
String value = base64Encode(f.readAsBytesSync());
String kk = "{'__class__': 'bytes', 'base64':" + value+ "}";
List<Map<String, dynamic>> vlist = List<Map<String, dynamic>>();
vlist.add({
"resource": 'wms.receiving,6',
"name": 'Ref_doc_.jpg' ,
"data": value
});
Future<TrytonResponse> create(List vlist, {Map context}) async {
var ctx = await getContext();
var params = [vlist, ctx];
String method = "model.ir.attachment.create";
var body = json.encode({"id": new Uuid().v1(),
"method": method,
"params": params});
final res = await callRequest(payload);
return res;
}
Future<TrytonResponse> callRequest(payload) async {
var auth = '$_userName:$_uid:$_sessionId';
var bytes = utf8.encode(auth);
var base64 = base64Encode(bytes);
String sessionAuth = 'Session $base64';
Dio client = Dio();
client.options.headers["Content-type"] = "application/json; charset=UTF-8";
client.options.headers["Cookie"] = _sessionId;
client.options.headers["authorization"] = sessionAuth;
final response = await client.post(_serverURL, data: body);
TrytonResponse res = TrytonResponse(response);
res.checkError();
return res;
}
bala4901
(Markus Bala)
December 1, 2020, 1:28am
7
Hi @german ,
Thank you for your help.
I think there is difference between json_rpc and tryton-flask.
Seem like, the code provided is using the connector which able to direct send the raw file as attachment.
Thank you
ced
(Cédric Krier)
December 1, 2020, 8:55am
8
This string representing a JSON will be encoded a second times.
bala4901:
"data": value
You are using the base64 value instead of the JSON representation.
bala4901
(Markus Bala)
July 5, 2021, 4:19pm
9
Sorry for long posting this thread. When posting using JSOn we need to user base64.
When go back to python, we need to change back to byte so it can be read.
Here I posted the solution. Hope it can help to others:
class Attachment(metaclass=PoolMeta):
__name__ = "ir.attachment"
@classmethod
def __setup__(cls):
super().__setup__()
cls.__rpc__.update(
{
"rft_attachment": RPC(readonly=False),
}
)
@classmethod
def rft_attachment(cls, values, *args):
if not values:
return
pool = Pool()
Attachment = pool.get("ir.attachment")
val = values[0]
base64data = val["data"]
filename = val["filename"]
resource = val["resource"]
imgdata = base64.b64decode(base64data)
(attach,) = Attachment.create(
[
{
"resource": resource,
"name": filename,
"data": imgdata,
}
]
)
return [{"value": True}]
1 Like
DaZD
(David Dormoy)
July 5, 2021, 6:31pm
10
Markus,
I found a solution without having to override Attachment :
String imagePath = "images/test.jpeg";
var imageData = await rootBundle.load(imagePath);
String value = base64Encode(imageData.buffer.asUint8List());
var kk = {'__class__': 'bytes', 'base64': value};
List<Map<String, dynamic>> vlist = <Map<String, dynamic>>[];
var params = {
"resource": 'product.template,43',
"name": 'test.jpg',
"data": kk
};
vlist.add(params);
call("model.ir.attachment", "create", [vlist, {}]);
You then can list the attachment like this :
call("model.ir.attachment", "search_read", [
['resource', '=', 'product.template,43'],
0,
null,
null,
['id', 'name'],
{}
]);
1 Like
bala4901
(Markus Bala)
July 6, 2021, 12:40am
11
Hi @DaZD ,
Eh… I did try this as per ced did mention.
But it failed too.
Nevermind, i try later.
Thank you… cheers
DaZD
(David Dormoy)
July 6, 2021, 1:01am
12
Yes ced gave the solution but to make it work with flutter the trick is to give an object instead of a string :
var kk = {'__class__': 'bytes', 'base64': value};
instead of :
String kk = "{'__class__': 'bytes', 'base64':" + value+ "}";
With a string value I had the same error message :
Unicode-objects must be encoded before hashing
system
(system)
Closed
August 5, 2021, 1:02am
13
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.