/// <inheritdoc /> public async Task <string> CreateFinalFileAsync(string[] partialFiles, string metadata, CancellationToken cancellationToken) { InternalFileRep[] partialInternalFileReps = new InternalFileRep[partialFiles.Length]; for (int i = 0; i < partialFiles.Length; i++) { partialInternalFileReps[i] = _fileRepFactory.Data(await InternalFileId.Parse(_fileIdProvider, partialFiles[i])); if (!partialInternalFileReps[i].Exist()) { throw new TusStoreException($"File {partialFiles[i]} does not exist"); } } var length = partialInternalFileReps.Sum(f => f.GetLength()); var fileId = await CreateFileAsync(length, metadata, cancellationToken); var internalFileId = await InternalFileId.Parse(_fileIdProvider, fileId); _fileRepFactory.UploadConcat(internalFileId).Write(new FileConcatFinal(partialFiles).GetHeader()); using (var finalFile = _fileRepFactory.Data(internalFileId).GetStream(FileMode.Open, FileAccess.Write, FileShare.None)) { foreach (var partialFile in partialInternalFileReps) { using var partialStream = partialFile.GetStream(FileMode.Open, FileAccess.Read, FileShare.Read); await partialStream.CopyToAsync(finalFile); } } if (_deletePartialFilesOnConcat) { await Task.WhenAll(partialInternalFileReps.Select(f => DeleteFileAsync(f.FileId, cancellationToken))); } return(fileId); }
private void MarkChunkComplete(InternalFileRep chunkComplete) { chunkComplete.Write("1"); }
/// <summary> /// Initializes a new instance of the <see cref="TusDiskFile"/> class. /// </summary> /// <param name="data">The file representation of the data</param> /// <param name="metadata">The file representation of the metadata</param> internal TusDiskFile(InternalFileRep data, InternalFileRep metadata) { Id = data.FileId; _data = data; _metadata = metadata; }