BoomDAO / ICP.NET

A library for .NET/C#/Unity to natively communicate with the Internet Computer (ICP)
MIT License
50 stars 3 forks source link

AssetCanisterApiClient.GetAsync - (Download Asset) is only returning first chunk #125

Closed stefan-adna closed 4 months ago

stefan-adna commented 5 months ago

When using the Download Asset as shown in the /samples/Sample.CLI project (which is using the GetAsync(string key, List<string> acceptEncodings) of the AssetCanister) I only get the bytes of the first chunk.

How can I download the whole file?

I noticed there is a GetChunkAsync method, but I don't know how many chunks are there in total for each file. Also I don't think that the user of this package should need to do this by himself.

Gekctek commented 5 months ago

Hmm. Not super familiar with the API itself. I auto generated the client with the ICP.NET generator, then threw in the upload via chunks. Based on the docs it seems that if there are multiple chunks, youll have to use the get_chunk for the additional chunks. Ill try to create a single method that will detect if there are multiple chunks and pull them down

get: (record {
    key: Key;
    accept_encodings: vec text;
  }) -> (record {
    content: blob; // may be the entirety of the content, or just chunk index 0
    content_type: text;
    content_encoding: text;
    sha256: opt blob; // sha256 of entire asset encoding, calculated by dfx and passed in SetAssetContentArguments
    total_length: nat; // all chunks except last have size == content.size()
  }) query;

  // if get() returned chunks > 1, call this to retrieve them.
  // chunks may or may not be split up at the same boundaries as presented to create_chunk().
  get_chunk: (record {
    key: Key;
    content_encoding: text;
    index: nat;
    sha256: opt blob;  // sha256 of entire asset encoding, calculated by dfx and passed in SetAssetContentArguments
  }) -> (record { content: blob }) query;
Gekctek commented 5 months ago

Im adding a new helper method DownloadAssetAsync that will get all the chunks if there are multiple

Gekctek commented 5 months ago

Fixed in 6.1.0

stefan-adna commented 4 months ago

@Gekctek I tested with new version and got the following exception when trying to download a text file (encoding=UTF-8) from AssetCanister

EdjCase.ICP.Agent.QueryRejectedException: Query was rejected. Code: CanisterError, Message: IC0503: Canister yaku6-4iaaa-aaaab-qacfa-cai trapped explicitly: no such encoding, ErrorCode: IC0503
   at EdjCase.ICP.Agent.Responses.QueryResponse.ThrowOrGetReply()
   at EdjCase.ICP.Agent.Standards.AssetCanister.AssetCanisterApiClient.GetAsync(String key, List`1 acceptEncodings)
   at EdjCase.ICP.Agent.Standards.AssetCanister.AssetCanisterApiClient.DownloadAssetAsync(String key, Int32 maxConcurrency)
   at AssetContainerClient.ICPConnector.DownloadDocument(String identifier) in D:\Code\Dfinity\AssetContainerClient\ICPConnector.cs:line 31
   at AssetContainerClient.Program.DownloadDocument(IICPConnector connector) in D:\Code\Dfinity\AssetContainerClient\Program.cs:line 99
   at AssetContainerClient.Program.Main(String[] args) in D:\Code\Dfinity\AssetContainerClient\Program.cs:line 57
Gekctek commented 4 months ago

@stefan-adna hmmm. Your content encoding is set to UTF-8? I believe it should be one of these: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding

I changed up the method to allow for overriding the Accept-Encoding if needed in https://github.com/BoomDAO/ICP.NET/pull/127 And you will be able to see what encoding was returned

But i think you should probably use on of the default encodings vs UTF-8

Gekctek commented 4 months ago

try https://github.com/BoomDAO/ICP.NET/releases/tag/6.1.1

stefan-adna commented 4 months ago

Hi @Gekctek You are right, I should have used one of the default encodings. Nevertheless I think it makes sense to let the caller specify the content-encoding, as he can also specify it in the upload method. Thanks a lot for the updated package.