|
Inicio → WINDEV 2024 → Téléchargement de documents reçu d'une application mobile android |
Téléchargement de documents reçu d'une application mobile android |
Iniciado por Jennifer, 09,abr. 2024 12:04 - 21 respuestas |
| |
| | | |
|
| |
Miembro registrado 16 mensajes |
|
Publicado el 09,abril 2024 - 12:04 |
Bonjour,
Je travaille en partenariat avec une société qui développe des applications mobiles. Une des fonctionnalités développées dans l'application mobile consiste à joindre des photos lors d'un échec de livraison. A ce moment-là, l'application mobile fait appel à un webservice (POST) que j'ai développé pour envoyer les documents (multi-part). Plusieurs documents peuvent être envoyés dans un unique appel service.
Je reste coincée depuis plusieurs jours sur le moyen de récupérer (sauvegarder) les documents qui me sont transmis.
Je ne sais pas dans quelle propriété est stocké le contenu du document. J'ai bien accès aux propriétés Content-Disposition et Content-Type mais cela ne m'aide pas vraiment.
Avez-vous des suggestions à faire. Je ne trouve pas dans l'aide.
Merci à tous, |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 3.912 mensajes Popularité : +227 (347 votes) |
|
Publicado el 09,abril 2024 - 12:45 |
Bonjour, C'est toi qui a conçu le WS donc tu connais la structure utilisée. A toi d'utiliser la même structure lors de la désérialisation.
-- Il y a peut être plus simple, mais, ça tourne |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 453 mensajes Popularité : +31 (43 votes) |
|
Publicado el 09,abril 2024 - 13:32 |
Bonjour
voici comment je fais pour récupérer une image envoyé d'un mobile à un ws que j'ai dev :
reponse est un JSON = WebserviceParamètre(paramBuffer)
chemin est une chaîne = reponse.chemin_fichier + [fSep()] + reponse.nom_fichier buffer_image est un Buffer = Decode(reponse.image, encodeBASE64) fSauveBuffer(chemin,buffer_image)
cdlt
DG |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 09,abril 2024 - 14:19 |
Bonjour Voroltinquo,
Merci pour ton aide. J'ai l'impression de ne pas tout comprendre encore mais j'avance en m'aidant de Postman. Quand je comprendrai le fonctionnement via Postman, je pourrai me pencher sur la liaison appli mobile webservice. J'ai donc un appel de mon service dans Postman. Je met plusieurs documents (file) dans le form-data body. Je reçois les infos sous cette forme :
Screenshot_20240409-132909.png;C:\WEBDEV 28\TmpUpload\WEBDEV_0_15124_-2011105307_31099511.upl
J'ai mis 2 photos et je ne vois que le nom d'une seule. Et quand je vais dans le dossier où est sensé se trouver le .upl je ne vois rien. Que dois-je faire de ça ?
Merci de ton aide, |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 09,abril 2024 - 14:39 |
Bonjour Dimitri G,
Si je met la ligne de code reponse est un JSON = WebserviceParamètre(paramBuffer) J'ai une erreur dans Posman "Le contenu de la requête est vide".
J'avoue ne pas y comprendre grand chose.Mensaje modificado, 09,abril 2024 - 14:39 |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 09,abril 2024 - 15:17 |
J'ai combiné vos deux suggestions et j'arrive bien à enregistrer l'image envoyée mais quand j'essaye de l'ouvrir j'ai un message "Paint can not read this file". Il faut aussi que je puisse enregistrer plusieurs images en un seul appel du WS. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 3.912 mensajes Popularité : +227 (347 votes) |
|
Publicado el 09,abril 2024 - 15:25 |
Je suppose que ta structure contient un tableau de buffers, destiné à recevoir les images
-- Il y a peut être plus simple, mais, ça tourne |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 09,abril 2024 - 15:42 |
Oui je viens d'adapter car ce n'était pas le cas. Mais le service reçoit les infos sous cette forme :
sFiles est une chaîne = WebserviceParamètre("file") sFiles => Screenshot_20240409-132909.png;C:\WEBDEV 28\TmpUpload\WEBDEV_0_15124_-2011105307_31099511.upl que je reçoive une ou plusieurs photos je n'ai toujours que ça comme info. Comment savoir le nombre de photos ? Et quel nom leur donner ? |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 453 mensajes Popularité : +31 (43 votes) |
|
Publicado el 09,abril 2024 - 15:47 |
pour exemple et même si cela ne répond pas complètement à votre problème, voici le code coté mobile qui permet d'envoyer une image au ws,
rq est un restRequête rp est une restRéponse
v est un JSON v.nom_fichier = "testimage.jpg" v.chemin_fichier = "\\SRV\Media\Photo"
image2 est une Image = "d:\phototest.jpg" bufBuffer est un Buffer = image2 v.image = Encode(bufBuffer,encodeBASE64)
rq.URL = "http://monwebservice/enregistrer_media" rq.Méthode = httpPost rq.ContentType = typeMimeJSON
rq.Contenu = v rp = RESTEnvoie(rq)
FIN |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 09,abril 2024 - 16:07 |
Ok, je comprend mieux en ayant les deux vues. Mais effectivement ça ne m'aide pas beaucoup pour résoudre mon cas. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 09,abril 2024 - 16:29 |
POST /xxxxxxx user-agent: Dart/3.3 (dart:io) content-type: multipart/form-data; boundary=dart-http-boundary-SFLrV_WnbR._bfPmI3p_HD72AE-AOBr9jXC-xGK_9QDJ3lK23z- accept-encoding: gzip content-length: 823212 token: xxxxxxxxxxxxxxxxxxxxxxxxx host: xxxxxxxxxxxxxxxxxxxxxxxxxxx
--dart-http-boundary-SFLrV_WnbR._bfPmI3p_HD72AE-AOBr9jXC-xGK_9QDJ3lK23z- content-type: application/octet-stream content-disposition: form-data; name="CAP9126106585719849515.jpg"; filename="CAP9126106585719849515.jpg"
ÿØÿá=¿Exif MM * Ð à ž ² ¸ À( 2 È ‡i ܈% È ÎZebra Technologies TC58 H H 2024:04:02 19:45:03 "‚š z‚ ‚ˆ" ˆ' ‚ 0220 Š ž ² º‘ ’ Â’ Ê’ Ò’ Ú’ â’ ’ ’ ’ ê’† Ÿ ò’ ’’‘ š’’ ¢ 0100 Ð à ©¢ £ ¤ ¤ ¤ ¤ (;šÊ ¥ d2024:04:02 19:45:03 2024:04:02 19:45:03 +02:00 +02:00 ú è d p d d ‚ èsensor mode:4, UC:1, feature:0 0, scene:0, effect:0 HDR scene detected 0, HDR failed 0 num HDR frames 0 EV table [0, 0, 0] MFNR Disable MFNR scene detected 1 239561 239561 239561 R98 0100 @ ð @ H( P 9g H H ÿØÿÛ „ !"$"$ÿ --dart-http-boundary-SFLrV_WnbR._bfPmI3p_HD72AE-AOBr9jXC-xGK_9QDJ3lK23z- content-type: application/octet-stream content-disposition: form-data; name="CAP901797041637942418.jpg"; filename="CAP901797041637942418.jpg"
ÿØÿáAaExif MM * Ð à ž ² ¸ À( 2 È ‡i ܈% ì òZebra Technologies TC58 H H 2024:04:02 19:45:09 "‚š z‚ ‚ˆ" ˆ' õ 0220 Š ž ² º‘ ’ Â’ Ê’ Ò’ Ú’ â’ ’ ’ ’ ê’† à ò’ ¶’‘ ¾’’ Æ 0100 Ð à Í¢ £ ¤ ¤ ¤ ¤ (;šÊ ¥ d2024:04:02 19:45:09 2024:04:02 19:45:09 +02:00 +02:00 ú è d ° d d ‚ èsensor mode:4, UC:1, feature:0 0, scene:0, effect:0 HDR scene detected 0, HDR failed 0 num HDR frames 1139638272 EV table [1137344512, 1137934336, 1138524160] MFNR Disable MFNR scene detected 1 599463 599463 599463 R98 0100 @ ð d l( t <å H H ÿØÿÛ „ !"$"$ÿÀ ð@" ÿÄ¢ } !1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚáâãäåæçèéêñòóôõö÷øùú w !1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³
Voici un exemple de ce que l'application m'envoie. Entre chaque "--dart-http-boundary" se trouve les infos liées à une image. Je ne sais pas quelle méthode WinDev utiliser pour simplement récupérer content-type et content-disposition pour chaque image. J'ai utilisé WebserviceParamètre mais en vain. Je fais appel à la méthode WebserviceLitEnteteHttp pour accéder au content-type et content-disposition généraux. ça fonctionne.
Et c'est encore plus flou pour récupérer le contenu de l'image qui semble associé à aucune variable.
J'espère que cet exemple vous permettra de cerner un peu mieux mes difficultés. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 3.912 mensajes Popularité : +227 (347 votes) |
|
Publicado el 09,abril 2024 - 16:47 |
Dans un premier temps, WebserviceParamètre renvoie un buffer et non une chaine. C'est ce buffer que tu va désérialiser. A partir de là tu aura accès au tableau contenant tes images, ou une structure contenant l'image et les infos. Le nombre d'image est la taille du tableau (son nombre d'occurrences) Grosso modo, ta structure/classe dois ressembler à çà
STImage est structure m_saNomImage est chaîne m_bufImage est Buffer FIN STEnvoi est une structure m_tabListeImage est tableau de STImage FIN
A la volée, les code ressemblent à ça :
stEnvoi est STEnvoi bufEnvoi est Buffer saURLRequete est chaîne
Sérialise(stEnvoi,bufEnvoi,psdBinaire)
HTTPRequête(saURLRequete,"","",bufEnvoi)
bufMsgReçu est un Buffer stMsg est STEnvoi
bufMsgReçu=WebserviceParamètre(paramBuffer) Désérialise(stMsg,bufMsgReçu,psdBinaire)
-- Il y a peut être plus simple, mais, ça tourneMensaje modificado, 09,abril 2024 - 16:48 |
| |
| |
| | | |
|
| | |
| |
Publicado el 10,abril 2024 - 16:58 |
Bonjour, Voici un exemple de code qui fonctionne parfaitement. Il faut passer les images/photos/documents en Json afin de récupérer en même temps d'autres informations, par exemple le nom du fichier etc...
Code d'envoi depuis le mobile
ParamId est Variant ParamId.NumChantier = gnum_chantier ParamId.NumCommande = gnum_commande SI NomFichier_1 <> "" ALORS ParamId.NomFichier_1 = NomFichier_1 ParamId.MonFichier_1 = FichierEncoder_1 SINON ParamId.NomFichier_1 = "" ParamId.MonFichier_1 = "" FIN ElementEnJSON est une chaîne ANSI = VariantVersJSON(ParamId)
MaQuestion est un restRequête MaRéponse est une restRéponse MaQuestion.URL = "http://"+Mon_IP_serveur+"/nom du webservice" MaQuestion.Contenu = ElementEnJSON MaQuestion.Méthode = httpPost MaQuestion.ContentType = "application/json" MaRéponse = RESTEnvoie(MaQuestion)
Code du webservice de WD pour enregistrer le fichier
Procedure Nom du la Procedure()
ElementEnJSON est une chaîne ANSI = WebserviceParamètre(paramBuffer) ParamId est un Variant = JSONVersVariant(ElementEnJSON) SI ParamId.NomFichier_1 <> "" ALORS SI fRepExiste(societe.chemin_chantier + "\" + ParamId.NumChantier + "\Commande\" + ParamId.NumCommande) = Faux ALORS fRepCrée(societe.chemin_chantier + "\" + ParamId.NumChantier + "\Commande\" + ParamId.NumCommande) FIN fSauveBuffer(societe.chemin_chantier + "\" + ParamId.NumChantier + "\Commande\" + ParamId.NumCommande + "\" + ParamId.NomFichier_1, Decode(ParamId.MonFichier_1, encodeBASE64)) SINON FIN RENVOYER Vrai
Et éventuellement si vous voulez le code pour sélectionner les fichiers depuis le mobile. Il se trouve dans le forum mobile https://forum.pcsoft.fr/fr-FR/pcsoft.fr.windevmobile/50082-selectionner-image-fichier-pdf/read.awp
Bon développement. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 15,abril 2024 - 16:57 |
Bonjour,
Merci beaucoup pour vos suggestions de code. J'ai essayé plusieurs choses mais je n'ai pas encore la solution pour répondre à mon problème.
L'utilisation de paramBuffer en tant que paramètre de la méthode WebserviceParamètre ne fonctionne pas chez moi.
J'ai récupéré le code implémenté dans l'application mobile pour cet envoi de pièces jointes justement. C'est en Flutter + Dart :
var request = MultipartRequest('Post', url); for (var a IN attachments) { request.files.add(await MultipartFile.fromPath( a.filename, a.path, filename: a.filename, )); }
Ainsi, je comprends bien que toutes les pièces jointes sont ajoutées dans le tableau de files avec pour chacun d'eux un nom de fichier (filename) et le chemin où est stocké le fichier en question (path).
De mon côté, dans le WS Windev j'ai fait ceci
STAttachment est une structure NomFicher est une chaîne ContenuFichier est un Buffer FIN STUploadResponse est une structure Files est un tableau de STAttachment FIN stUploadRep est un STUploadResponse bufFiles est un Buffer = WebserviceParamètre("files") Désérialise(stUploadRep,bufFiles,psdBinaire) fLogger.InfoMsg(ChaîneConstruit("ATTACHMENTS ParamId : %1",stUploadRep.Files.Occurrence()))
Je ne suis pas certaine des noms à utiliser de mon côté. En tout cas pour le moment ça coince et le message InfoMsg ne s'écrit pas.
Merci de votre aide. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 402 mensajes Popularité : +13 (13 votes) |
|
Publicado el 15,abril 2024 - 17:17 |
Bonjour,
A la vue de la requête client HTTP du post #11, on est sur de l'upload classique en multipart/form-data, c'est-à-dire comme avec un champ d'upload en WebDev. Dans ce cas, en règle générale, on a des aides (par exemple, en PHP il y a la variable globale $_FILES, en WebDev "classique" hors-webservice, on a les fonction UploadXXX()). Mais pas en webservice.
Voilà ce qu'il faut à peu près faire : - depuis l'entête général "Content-Type", récupérer la "boundary" utilisée pour le reste de la requête : c'est cette boundary (en français "limite", "borne"), générée dynamiquement par le client, qui permet de séparer le contenu de la requête en différents morceaux - récupérer le buffer représentant le contenu de la requête : ça peut être via WebserviceParamètre(paramBuffer), ou par un paramètre de type Buffer dans les arguments de la procédure (et la liaison dans la description du point d'entrée) - découper le buffer en plusieurs morceaux utilisant la chaine "--" + boundary - Pour chaque morceaux, vous allez donc avoir plusieurs éléments : - un content-type qui donne le type de la data qui suit, - un content-disposition qui en donne plusieurs informations, comme le nom du fichier - puis, après un saut de ligne, vous aurez le buffer correspondant au fichier - avec tous ces bouts vous devriez pouvoir alors sauvegarder votre fichier. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 16,abril 2024 - 08:24 |
Bonjour bchnaudet,
Merci beaucoup pour ton explications détaillées des étapes à faire. Je pense avoir compris le principe. Voici ce que j'ai mis en place pour le moment :
sContentTypeGlobal est une chaîne = WebserviceLitEntêteHTTP("Content-Type") fLogger.InfoMsg(ChaîneConstruit("ATTACHMENTS Content-Type : %1",sContentTypeGlobal)) sBoundary est une chaîne = ExtraitChaîne(sContentTypeGlobal,2,"boundary=",DepuisDébut) fLogger.InfoMsg(ChaîneConstruit("ATTACHMENTS sBoundary : %1",sBoundary)) bufCont est un Buffer = WebserviceParamètre(paramBuffer) fLogger.InfoMsg(ChaîneConstruit("ATTACHMENTS Taille(bufCont) : %1",Taille(bufCont))) sImg1 est une chaîne = ExtraitChaîne(bufCont,2,sBoundary,DepuisDébut) fLogger.InfoMsg(ChaîneConstruit("ATTACHMENTS sImg1 : %1",sImg1)) sContentTypeImg1 est une chaîne = ExtraitChaîne(sImg1,1,"content-type",DepuisDébut) fLogger.InfoMsg(ChaîneConstruit("ATTACHMENTS sContentTypeImg1 : %1",sContentTypeImg1)) sContentDispositionImg1 est une chaîne = ExtraitChaîne(sImg1,1,"content-disposition",DepuisDébut) fLogger.InfoMsg(ChaîneConstruit("ATTACHMENTS sContentDispositionImg1 : %1",sContentDispositionImg1))
J'arrive bien à récupérer l'entête générale dans la variable sContentTypeGlobal ainsi que la boundary dans la variable sBoundary. Par contre, la récupération du buffer via WebserviceParamètre(paramBuffer) n'abouti pas. Les étapes suivantes ne sont pas traitées. Comme si le service était bloqué. L'alternative que vous proposiez en utilisant un paramètre de type buffer dans les arguments de la procédure nécessiterait de modifier l'appel du service dans l'apk flutter et cela n'est pas possible.
Merci pour votre aide, |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 402 mensajes Popularité : +13 (13 votes) |
|
Publicado el 16,abril 2024 - 10:00 |
Bonjour,
Comme quoi il est toujours bon de tester, et comme quoi on en apprend tous les jours....
Après quelques tests, il semblerait que dans ce cas précis (upload de fichiers classique sur un point d'entrée de webservice REST), WebDev détecte que la requête contient des fichiers uploadés, et les traite déjà en interne avant d'envoyer le contenu au code du point d'entrée. Il détecte aussi la boundary tout seul et met les différents contenus dans différents paramètres.
C'est pourquoi WebserviceParamètre(paramBuffer) ne fonctionne pas, car le contenu de la requête est traité en amont et est donc "vide" au moment d'arriver au code du projet.
Un code qui fonctionne (et testé cette fois) :
i est un entier = 1 bufParam est un Buffer = WebserviceParamètre(i)
TANTQUE bufParam <> "" Trace(bufParam) i++ bufParam = WebserviceParamètre(i) FIN
RENVOYER Vrai
Note : le format d'entrée du point d'entrée doit être sur "Variable" ou "Formulaire HTML". J'ai testé le code en v28, pas en v2024
Pour chaque fichier uploadé, vous allez recevoir dans bufParam une chaîne contenant : le nom du fichier, puis après un point-virgule, le chemin du fichier temporaire sur le serveur du fichier uploadé. Il suffira de copier et renommer ce fichier à l'endroit où vous le souhaitez.
Il est assez particulier que WebDev ne permette pas, même en indiquant le format le plus souple d'entrée ("Variable"), de réellement récupérer le contenu sans aucun traitement en amont. Il serait peut-être pertinent de le signaler au support technique pour éventuellement une amélioration dans les prochaines versions. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 16,abril 2024 - 10:27 |
Bonjour,
Merci beaucoup pour ses explications très claires. J'ai bien le format du point d'entrée en "Formulaire HTML" J'utilise WD28. J'ai pris le morceau de code que vous m'avez envoyer. Par contre de mon côté bufParam est vide. J'ai 2 images qui me sont envoyées mais Taille(bufParam) = 0. Du coup je ne rentre pas dans la boucle du TANTQUE...
Il y a encore un mystère Windev à perser. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 16,abril 2024 - 10:46 |
J'ai essayé ceci mais ça ne change rien :
bufParam est un Buffer = WebserviceParamètre("") Taille(bufParam- vaut toujours 0. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 16,abril 2024 - 10:54 |
En mettant le format du point d'entrée à "Variable" cela n'a rien changé non plus. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 18,abril 2024 - 08:20 |
Bonjour,
Quelqu'un aurait une idée. Je suis dans une impasse.
Merci de votre aide. |
| |
| |
| | | |
|
| | |
| |
Miembro registrado 16 mensajes |
|
Publicado el 18,abril 2024 - 10:34 |
Bonjour,
Merci beaucoup bchanudet pour ton aide. J'ai réussi à sauvegarder une image. Cela fonctionne quand j'utilise Postman. Le buffer contient bien les infos de l'image et le déplacement et renommage me permet bien de pouvoir afficher l'image transmise.
Seul hic c'est qu'il semble qu'avec les infos fournies par la méthode Flutter (via l'apk) cela ne fonctionne pas de la même manière. bufParam reste désespérément vide 😒
Je continue de chercher... |
| |
| |
| | | |
|
| | | | |
| | |
|