Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/badges/tests.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions src/ndi/+ndi/+cloud/+api/+implementation/+files/GetFile.m
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,15 @@
b = false;
apiURL = this.downloadURL; % Return the URL as a string

command = sprintf('curl -L -o "%s" "%s"', this.downloadedFile, this.downloadURL);
% Our payloads are already compressed archives (.zip, .nbf.tgz).
% Asking the gateway to apply HTTP compression on top of that
% buys nothing and has produced corrupt archives on both Mac
% and Linux (stream decoders fail on already-compressed bytes).
% Request identity encoding so the raw file is delivered as-is.
% Use -f so HTTP errors surface as non-zero exit codes instead
% of writing a server error body into the destination file.
command = sprintf('curl -fsSL -H "Accept-Encoding: identity" -o "%s" "%s"', ...
this.downloadedFile, this.downloadURL);

[status, result] = system(command);

Expand All @@ -69,4 +77,4 @@
apiResponse = struct('StatusCode', 'N/A (cURL)', 'StatusLine', "Exit Status: " + status);
end
end
end
end
9 changes: 7 additions & 2 deletions src/ndi/+ndi/+cloud/+download/downloadDatasetFiles.m
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,14 @@ function downloadDatasetFiles(cloudDatasetId, targetFolder, fileUuids, options)
end
downloadURL = answer.downloadUrl;

% Save the file
% Save the file using curl so gateway-level HTTP compression
% does not corrupt the saved bytes (websave auto-decompresses).
try
websave(targetFilepath, downloadURL);
[success_d, answer_d] = ndi.cloud.api.files.getFile(downloadURL, targetFilepath, 'useCurl', true);
if ~success_d
error('NDI:Cloud:FileDownloadFailed', ...
'curl download failed: %s', char(string(answer_d)));
end
catch ME
if options.AbortOnError
rethrow(ME)
Expand Down
16 changes: 12 additions & 4 deletions src/ndi/+ndi/+cloud/+download/downloadDocumentCollection.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
% directly to avoid an extra API call to fetch the list again.
%
% options.Timeout - (1,1) double, optional
% The timeout in seconds for the websave download operation.
% The timeout in seconds for the download operation.
% Default is 20.
%
% options.ChunkSize - (1,1) double, optional
Expand Down Expand Up @@ -107,20 +107,28 @@

isFinished = false;
t1 = tic;
lastErr = '';
% The download URL may not be immediately ready. Retry until timeout.
% Use curl (not websave) so the response body is written as-is; HTTP
% content-encoding applied at the gateway otherwise corrupts the zip.
while ~isFinished && toc(t1) < options.Timeout
try
websave(tempZipFilepath, downloadUrl);
[success_d, answer_d] = ndi.cloud.api.files.getFile(downloadUrl, tempZipFilepath, 'useCurl', true);
if ~success_d
lastErr = char(string(answer_d));
error('NDI:Cloud:DocumentDownloadFailed', 'curl download failed: %s', lastErr);
end
isFinished = true;
catch ME
lastErr = ME.message;
pause(1) % Wait a second before retrying
end
end

if ~isFinished
error('NDI:Cloud:DocumentDownloadFailed', ...
['Download failed for chunk %d with message:\n %s\n. If this persists, ', ...
'consider increasing the Timeout value.'], c, ME.message);
'consider increasing the Timeout value.'], c, lastErr);
end

% Unzip and process documents from the current chunk
Expand Down Expand Up @@ -156,4 +164,4 @@ function deleteIfExists(filePath)
if isfile(filePath)
delete(filePath)
end
end
end
8 changes: 7 additions & 1 deletion src/ndi/+ndi/+cloud/+download/downloadGenericFiles.m
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,14 @@
continue;
end

% Download using curl so gateway-level HTTP compression does not
% corrupt the saved bytes (websave auto-decompresses responses).
try
websave(targetPath, answer.downloadUrl);
[success_d, answer_d] = ndi.cloud.api.files.getFile(answer.downloadUrl, targetPath, 'useCurl', true);
if ~success_d
error('NDI:downloadGenericFiles:DownloadError', ...
'curl download failed: %s', char(string(answer_d)));
end
downloadedFiles(end+1) = filename; %#ok<AGROW>
catch ME
warning('NDI:downloadGenericFiles:DownloadError', ...
Expand Down