Re: Question ZnClient with file

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: Question ZnClient with file

Sven Van Caekenberghe-2
Hi,

CC'ing the Pharo Users ML since that gives a permanent record of my answer.

File uploads using ZnClient do work in the common case. You can check ZnServerTest>>#testFormTest3 or ZnImageExampleDelegateTest>>#testUpload as well as several other senders of #addPart:

First you are mixing 2 types of forms (see https://ci.inria.fr/pharo-contribution/job/EnterprisePharoBook/lastSuccessfulBuild/artifact/book-result/Zinc-HTTP-Client/Zinc-HTTP-Client.html section 6. Submitting HTML Forms).

For a file upload you need a ZnMultiPartFormDataEntity which is configured automatically in ZnClient by #multiPartFormDataEntity when you do #addPart: (no need to set a content type).

Next you are mixing the file name and the file contents. It is best to use the class side ZnMimePart instance creation methods, either #fieldName:fileName:entity: or #fieldName:fileNamed:

Also, when you create a ZnByteArray entity with the contents of a .jpg or .png you not only have to load the actual bytes (obviously), but you also have to set the mime type correctly. In #fieldName:fileNamed: you can see how this is done by using the file extension, but that is just one way to do it, if you know the type upfront, just set it.

There is also ZnClient>>#uploadEntityFrom: (used by #testUploadSmallDocument) but that is not using a form.

I am sure you will be able to figure it out, if not just ask.

Sven

> On 30 Aug 2020, at 09:51, Sabine Manaa <[hidden email]> wrote:
>
> Hi Sven,
>
> I hope you are well this serious times!
>
> I have a problem with ZnClient. I was asking yesterday in Discord but
> we did not find a solution.
>
> https://discordapp.com/channels/223421264751099906/223421264751099906/749313351859044382
>
> I write a summary here:
>
> I have this command, which works fine on the command line:
>
> curl -X POST "https://my.sevdesk.de/api/v1/Voucher/Factory/uploadTempFile?token=32695d076245b124b0faaa56afc71b74"
> -H "accept: application/xml" -H "Content-Type: multipart/form-data" -F
> "file=@/Users/sabine/Desktop/belege/neue_belege/mcdonalds.jpeg;type=image/jpeg"
>
> Now, I want to "translate" this in a ZnClient command, but I do not
> get it. my command is:
>
> ^ ZnClient new
>   systemPolicy;
>   https;
>   accept: ZnMimeType applicationXml;
>   headerAt: 'Content-Type' add: 'multipart/form-data';
>   host: 'my.sevdesk.de';
>   path: '/api/v1/Voucher/Factory/uploadTempFile?token=32695d076245b124b0faaa56afc71b74';
>   ifFail: [ :exception | exception response entity inspect ];
>   formAt: 'file' put:
> '@/Users/sabine/Desktop/belege/neue_belege/mcdonalds.jpeg';
>   formAt: 'type' put: 'image/jpeg';
>   post
>
> There must be a difference between the command line and the ZnClient
> command because with the ZnClient command, I get this error:
> {"objects":null,"error":{"message":"Uploaded file is not inside the
> allowed directory","code":null,"data":null}}.
>
> I was also trying to get the command line from the ZnClient instance
> with the method curl but that gives me this:
>
> echo 66696c653d402f55736572732f736162696e652f4465736b746f702f62656c6567652f6e6575655f62656c6567652f6d63646f6e616c64732e6a70656726747970653d696d6167652f6a706567
> | xxd -r -p | curl -X POST
> https://my.sevdesk.de:443/api/v1/Voucher/Factory/uploadTempFile?token=32695d076245b124b0faaa56afc71b74
> -H"User-Agent:Zinc HTTP Components 1.0 (Pharo/7.0)"
> -H"Accept:application/xml"
> -H"Content-Type:application/x-www-form-urlencoded"
> -H"Host:my.sevdesk.de" -H"Content-Length:77" --data-binary @-
>
> Would be very nice if you could help me. All I want ist to "translate"
> the above curl command in a corresponding ZnClient command....
>
> Regards
> Sabine


Reply | Threaded
Open this post in threaded view
|

Re: Question ZnClient with file

Sven Van Caekenberghe-2


> On 30 Aug 2020, at 18:05, Sabine Manaa <[hidden email]> wrote:
>
> Hi Sven,
>
> thanks a lot for your answer! I was already replying 3 hours ago but my answer did not pass the mailing list.
>
> Perhaps you can answer this mail for the mailing list again:
>
> I was writing:
>
> Hi Sven,
> you see me here very happy here.
> It is much simpler as I was thinking. Just:
>
> ^ ZnClient new
> url:
> 'https://my.sevdesk.de/api/v1/Voucher/Factory/uploadTempFile?token=32695d076245b124b066faaa56afc71b74';
> addPart:
> (ZnMimePart
> fieldName: 'file'
> fileNamed: '/Users/sabine/Desktop/belege/neue_belege/mcdonalds.jpeg');
> post
>
> With this, it succeeds with the upload.

Great.

In production you should also check whether the upload succeeded.

One way to do this is by using #enforceHttpSuccess - this will signal an exception unless the host returned a 200 or similar code (assuming the receiving host acts like this).

> ...
>
> Please allow me to ask one more question:
>
> My situation in my application is, that I do not have the file local as in the example but in amazon S3 and I have a url like this:
>
> https://s3.eu-central-1.amazonaws.com/spf-belege-dev/K1000137/201905061113-506963984-9575877/31/7/small-202008241549-7987688-1.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJUHEWICJ33EJAUMA%2F20200830%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Date=20200830T155656Z&X-Amz-Expires=6000&X-Amz-SignedHeaders=host&X-Amz-Signature=ab3f329b1e63c896f8hh95e36951f199fae081ca
>
> My question is: Is it possible to NOT download this file to my server for then sending it with filename and path to the other system but setting this url directly in the ZnClient?
> For the other system it has to be like a file upload...
> This would save transfer costs and time.

I understand, but unless the host supports this, there is not much you can do. The data has to be transferred, if they are not willing to fetch it from some URL, you will have to do the copying.

If the files are not too large, you can take them temporarily in memory if you want (so that you do not have to create a temp file).

See ZnImageExampleDelegateTest and how #testUpload uses #image there.

It probably would also work with a ZnStreamingEntity (so that not everything has to be in memory at the same time, just the buffer to do stream copying), but that might require some more experimenting.

> Regards
> Sabine
>  
>
> Sabine
>
> Am So., 30. Aug. 2020 um 14:48 Uhr schrieb Sabine Manaa <[hidden email]>:
> Hi Sven,
>
> you see me here very happy here.
>
> It is much simpler as I was thinking. Just:
>
> ^ ZnClient new
> url:
> 'https://my.sevdesk.de/api/v1/Voucher/Factory/uploadTempFile?token=32695d076245b124b0faaa56afc71b74';
> addPart:
> (ZnMimePart
> fieldName: 'file'
> fileNamed: '/Users/sabine/Desktop/belege/neue_belege/mcdonalds.jpeg');
> post
>
> succeeds with the upload.
>
> Thank you very very much!
> I write this in discord, too.
>
> Sabine
>
> Am So., 30. Aug. 2020 um 14:03 Uhr schrieb Sven Van Caekenberghe-2 [via Smalltalk] <[hidden email]>:
> Hi,
>
> CC'ing the Pharo Users ML since that gives a permanent record of my answer.
>
> File uploads using ZnClient do work in the common case. You can check ZnServerTest>>#testFormTest3 or ZnImageExampleDelegateTest>>#testUpload as well as several other senders of #addPart:
>
> First you are mixing 2 types of forms (see https://ci.inria.fr/pharo-contribution/job/EnterprisePharoBook/lastSuccessfulBuild/artifact/book-result/Zinc-HTTP-Client/Zinc-HTTP-Client.html section 6. Submitting HTML Forms).
>
> For a file upload you need a ZnMultiPartFormDataEntity which is configured automatically in ZnClient by #multiPartFormDataEntity when you do #addPart: (no need to set a content type).
>
> Next you are mixing the file name and the file contents. It is best to use the class side ZnMimePart instance creation methods, either #fieldName:fileName:entity: or #fieldName:fileNamed:
>
> Also, when you create a ZnByteArray entity with the contents of a .jpg or .png you not only have to load the actual bytes (obviously), but you also have to set the mime type correctly. In #fieldName:fileNamed: you can see how this is done by using the file extension, but that is just one way to do it, if you know the type upfront, just set it.
>
> There is also ZnClient>>#uploadEntityFrom: (used by #testUploadSmallDocument) but that is not using a form.
>
> I am sure you will be able to figure it out, if not just ask.
>
> Sven
>
> > On 30 Aug 2020, at 09:51, Sabine Manaa <[hidden email]> wrote:
> >
> > Hi Sven,
> >
> > I hope you are well this serious times!
> >
> > I have a problem with ZnClient. I was asking yesterday in Discord but
> > we did not find a solution.
> >
> > https://discordapp.com/channels/223421264751099906/223421264751099906/749313351859044382
> >
> > I write a summary here:
> >
> > I have this command, which works fine on the command line:
> >
> > curl -X POST "https://my.sevdesk.de/api/v1/Voucher/Factory/uploadTempFile?token=32695d076245b124b0faaa56afc71b74"
> > -H "accept: application/xml" -H "Content-Type: multipart/form-data" -F
> > "file=@/Users/sabine/Desktop/belege/neue_belege/mcdonalds.jpeg;type=image/jpeg"
> >
> > Now, I want to "translate" this in a ZnClient command, but I do not
> > get it. my command is:
> >
> > ^ ZnClient new
> >   systemPolicy;
> >   https;
> >   accept: ZnMimeType applicationXml;
> >   headerAt: 'Content-Type' add: 'multipart/form-data';
> >   host: 'my.sevdesk.de';
> >   path: '/api/v1/Voucher/Factory/uploadTempFile?token=32695d076245b124b0faaa56afc71b74';
> >   ifFail: [ :exception | exception response entity inspect ];
> >   formAt: 'file' put:
> > '@/Users/sabine/Desktop/belege/neue_belege/mcdonalds.jpeg';
> >   formAt: 'type' put: 'image/jpeg';
> >   post
> >
> > There must be a difference between the command line and the ZnClient
> > command because with the ZnClient command, I get this error:
> > {"objects":null,"error":{"message":"Uploaded file is not inside the
> > allowed directory","code":null,"data":null}}.
> >
> > I was also trying to get the command line from the ZnClient instance
> > with the method curl but that gives me this:
> >
> > echo 66696c653d402f55736572732f736162696e652f4465736b746f702f62656c6567652f6e6575655f62656c6567652f6d63646f6e616c64732e6a70656726747970653d696d6167652f6a706567
> > | xxd -r -p | curl -X POST
> > https://my.sevdesk.de:443/api/v1/Voucher/Factory/uploadTempFile?token=32695d076245b124b0faaa56afc71b74
> > -H"User-Agent:Zinc HTTP Components 1.0 (Pharo/7.0)"
> > -H"Accept:application/xml"
> > -H"Content-Type:application/x-www-form-urlencoded"
> > -H"Host:my.sevdesk.de" -H"Content-Length:77" --data-binary @-
> >
> > Would be very nice if you could help me. All I want ist to "translate"
> > the above curl command in a corresponding ZnClient command....
> >
> > Regards
> > Sabine
>
>
>
>
> If you reply to this email, your message will be added to the discussion below:
> http://forum.world.st/Re-Question-ZnClient-with-file-tp5121057.html
> To start a new topic under Pharo Smalltalk Users, email [hidden email]
> To unsubscribe from Pharo Smalltalk Users, click here.
> NAML