@@ -42,8 +42,8 @@ import { v7 as uuidv7 } from "uuid";
4242
4343import type { FilesUploadTab_PaginationQuery } from "@/api/__generated__/FilesUploadTab_PaginationQuery.graphql" ;
4444import type { FilesUploadTab_createFileDownloadRequestPresignedUrl_Mutation } from "@/api/__generated__/FilesUploadTab_createFileDownloadRequestPresignedUrl_Mutation.graphql" ;
45- import type { FilesUploadTab_createManualFileDownloadRequest_Mutation } from "@/api/__generated__/FilesUploadTab_createManualFileDownloadRequest_Mutation.graphql" ;
4645import type { FilesUploadTab_createManagedFileDownloadRequest_Mutation } from "@/api/__generated__/FilesUploadTab_createManagedFileDownloadRequest_Mutation.graphql" ;
46+ import type { FilesUploadTab_createManualFileDownloadRequest_Mutation } from "@/api/__generated__/FilesUploadTab_createManualFileDownloadRequest_Mutation.graphql" ;
4747import type { FilesUploadTab_fileDownloadRequests$key } from "@/api/__generated__/FilesUploadTab_fileDownloadRequests.graphql" ;
4848import type { FilesUploadTab_getRepositories_Query } from "@/api/__generated__/FilesUploadTab_getRepositories_Query.graphql" ;
4949
@@ -60,7 +60,11 @@ import type {
6060 FileDestinationType ,
6161 ManualFileDownloadRequestFromRepositoryData ,
6262} from "@/forms/validation" ;
63- import { computeDigest , createTarGzArchive } from "@/lib/files" ;
63+ import {
64+ computeDigest ,
65+ createTarArchive ,
66+ getUploadRequestHeaders ,
67+ } from "@/lib/files" ;
6468
6569// We use graphql fields below in columns configuration
6670/* eslint-disable relay/unused-fields */
@@ -217,13 +221,17 @@ const formatRelayErrors = (
217221type ManualFileDownloadRequestFormWrapperProps = {
218222 setErrorFeedback : ( feedback : React . ReactNode ) => void ;
219223 deviceId : string ;
224+ supportedEncodings : string [ ] ;
225+ allowArchiveUpload : boolean ;
220226 showAdvancedOptions : boolean ;
221227 destinationTypeOptions : DestinationTypeOption [ ] ;
222228} ;
223229
224230const ManualFileDownloadRequestFormWrapper = ( {
225231 setErrorFeedback,
226232 deviceId,
233+ supportedEncodings,
234+ allowArchiveUpload,
227235 showAdvancedOptions,
228236 destinationTypeOptions,
229237} : ManualFileDownloadRequestFormWrapperProps ) => {
@@ -264,6 +272,7 @@ const ManualFileDownloadRequestFormWrapper = ({
264272 const {
265273 files,
266274 archiveName,
275+ encoding,
267276 destinationType,
268277 destination,
269278 ttlSeconds,
@@ -276,7 +285,6 @@ const ManualFileDownloadRequestFormWrapper = ({
276285 let uploadBlob : Blob ;
277286 let fileName : string ;
278287 let uncompressedSize : number ;
279- let encoding : string | null = null ;
280288
281289 // Files from folder selection have webkitRelativePath set.
282290 // These need archiving even if there's only one file, to preserve
@@ -285,27 +293,18 @@ const ManualFileDownloadRequestFormWrapper = ({
285293 const needsArchive = files . length > 1 || hasRelativePaths ;
286294
287295 if ( needsArchive ) {
288- // Multiple files or folder contents: create tar.gz archive
289- uploadBlob = await createTarGzArchive ( files ) ;
290- const baseName = archiveName ?. trim ( ) || "files-archive" ;
291- fileName = baseName . endsWith ( ".tar.gz" )
292- ? baseName
293- : `${ baseName } .tar.gz` ;
296+ // Multiple files or folder content are uploaded as an archive
297+ uploadBlob = await createTarArchive ( files ) ;
298+ fileName = archiveName ?. trim ( ) || "files-archive" ;
294299 uncompressedSize = files . reduce ( ( sum , f ) => sum + f . size , 0 ) ;
295- encoding = "tar.gz" ;
296300 } else {
297301 uploadBlob = files [ 0 ] ;
298302 fileName = files [ 0 ] . name ;
299303 uncompressedSize = files [ 0 ] . size ;
300304 }
301305
302- if ( files . length === 1 && / \. ( t a r \. g z | t g z ) $ / i. test ( files [ 0 ] . name ) ) {
303- encoding = "tar.gz" ;
304- }
305-
306- const archiveData = new Uint8Array ( await uploadBlob . arrayBuffer ( ) ) ;
307306 const fileDownloadRequestId = uuidv7 ( ) ;
308- const digest = await computeDigest ( archiveData ) ;
307+ const digest = await computeDigest ( uploadBlob ) ;
309308
310309 // Get presigned URL from the backend
311310 const presignedUrls = await new Promise < {
@@ -361,7 +360,7 @@ const ManualFileDownloadRequestFormWrapper = ({
361360 // Upload the file to the presigned PUT URL
362361 const uploadResponse = await fetch ( presignedUrls . put_url , {
363362 method : "PUT" ,
364- headers : { "x-ms-blob-type" : "BlockBlob" } ,
363+ headers : getUploadRequestHeaders ( presignedUrls . put_url ) ,
365364 body : uploadBlob ,
366365 } ) ;
367366
@@ -459,6 +458,7 @@ const ManualFileDownloadRequestFormWrapper = ({
459458 deviceId ,
460459 getPresignedUrl ,
461460 createFileDownloadRequest ,
461+ allowArchiveUpload ,
462462 intl ,
463463 setErrorFeedback ,
464464 ] ,
@@ -468,6 +468,8 @@ const ManualFileDownloadRequestFormWrapper = ({
468468 < ManualFileDownloadRequestForm
469469 isLoading = { isUploading }
470470 onFileSubmit = { handleFileUpload }
471+ supportedEncodings = { supportedEncodings }
472+ allowArchiveUpload = { allowArchiveUpload }
471473 showAdvancedOptions = { showAdvancedOptions }
472474 destinationTypeOptions = { destinationTypeOptions }
473475 />
@@ -519,12 +521,6 @@ const ManualFileDownloadRequestFromRepositoryFormWrapper = ({
519521 groupId,
520522 } = values ;
521523
522- let encoding : string | null = null ;
523-
524- if ( / \. ( t a r \. g z | t g z ) $ / i. test ( file . name ) ) {
525- encoding = "tar.gz" ;
526- }
527-
528524 const fileDownloadRequestId = uuidv7 ( ) ;
529525
530526 // Create the file download request with all metadata
@@ -535,7 +531,6 @@ const ManualFileDownloadRequestFromRepositoryFormWrapper = ({
535531 deviceId,
536532 fileDownloadRequestId,
537533 fileId : file . id ,
538- encoding,
539534 fileMode,
540535 userId,
541536 groupId,
@@ -702,6 +697,33 @@ const FilesUploadTab = ({
702697 [ data . fileTransferCapabilities ?. targets , intl ] ,
703698 ) ;
704699
700+ const supportedEncodings = useMemo ( ( ) => {
701+ const uniqueEncodings = new Set < string > ( ) ;
702+
703+ data . fileTransferCapabilities ?. encodings ?. forEach ( ( encoding ) => {
704+ const value = encoding ?. trim ( ) ;
705+
706+ if ( value ) {
707+ uniqueEncodings . add ( value ) ;
708+ }
709+ } ) ;
710+
711+ return Array . from ( uniqueEncodings ) ;
712+ } , [ data . fileTransferCapabilities ?. encodings ] ) ;
713+
714+ const allowArchiveUpload = useMemo (
715+ ( ) =>
716+ supportedEncodings . some ( ( encoding ) => {
717+ const normalizedEncoding = encoding . trim ( ) . toLowerCase ( ) ;
718+ return (
719+ normalizedEncoding === "tar" ||
720+ normalizedEncoding === "tar.gz" ||
721+ normalizedEncoding === "tar.lz4"
722+ ) ;
723+ } ) ,
724+ [ supportedEncodings ] ,
725+ ) ;
726+
705727 if ( destinationTypeOptions ?. length === 0 ) {
706728 return null ;
707729 }
@@ -766,6 +788,8 @@ const FilesUploadTab = ({
766788 < ManualFileDownloadRequestFormWrapper
767789 setErrorFeedback = { setErrorFeedback }
768790 deviceId = { deviceId }
791+ supportedEncodings = { supportedEncodings }
792+ allowArchiveUpload = { allowArchiveUpload }
769793 showAdvancedOptions = { showAdvancedOptions }
770794 destinationTypeOptions = { destinationTypeOptions }
771795 />
0 commit comments