Skip to content

Commit c4d777b

Browse files
Fix UploadLarge breaking large files on upload
1 parent defa08d commit c4d777b

File tree

3 files changed

+49
-39
lines changed

3 files changed

+49
-39
lines changed

CloudinaryDotNet.IntegrationTests/IntegrationTestBase.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Linq;
55
using System.Net.Http;
66
using System.Reflection;
7+
using System.Security.Cryptography;
78
using System.Threading.Tasks;
89
using CloudinaryDotNet.Actions;
910
using NUnit.Framework;
@@ -507,6 +508,18 @@ protected string GetUniqueMetadataFieldLabel(string suffix = "")
507508
return label;
508509
}
509510

511+
protected static string GetFileMd5Sum(string filename)
512+
{
513+
using (var md5 = MD5.Create())
514+
{
515+
using (var stream = File.OpenRead(filename))
516+
{
517+
var hash = md5.ComputeHash(stream);
518+
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
519+
}
520+
}
521+
}
522+
510523
[OneTimeTearDown]
511524
public virtual void Cleanup()
512525
{

CloudinaryDotNet.IntegrationTests/UploadApi/UploadMethodsTest.cs

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ public class UploadMethodsTest : IntegrationTestBase
4040

4141
protected string m_implicitTransformationText;
4242

43+
protected string m_largeFileEtag;
44+
protected int m_largeFileLength;
45+
4346
public override void Initialize()
4447
{
4548
base.Initialize();
@@ -52,6 +55,9 @@ public override void Initialize()
5255
m_transformationAr25, m_transformationAr69,
5356
m_transformationAr30, m_transformationAr12,
5457
m_eagerTransformation);
58+
59+
m_largeFileEtag = GetFileMd5Sum(m_testLargeImagePath);
60+
m_largeFileLength = (int)new FileInfo(m_testLargeImagePath).Length;
5561
}
5662

5763
[Test, RetryWithDelay]
@@ -576,7 +582,7 @@ public void TestUploadLargeNonSeekableStream()
576582

577583
var result = m_cloudinary.UploadLarge(uploadParams, TEST_CHUNK_SIZE);
578584

579-
AssertUploadLarge(result, bytes.Length);
585+
AssertUploadLarge(result);
580586
}
581587
}
582588

@@ -585,27 +591,25 @@ public void TestUploadLargeRawFiles()
585591
{
586592
// support uploading large raw files
587593
var largeFilePath = m_testLargeImagePath;
588-
int largeFileLength = (int)new FileInfo(largeFilePath).Length;
589594

590595
var uploadParams = GetUploadLargeRawParams(largeFilePath);
591596

592597
var result = m_cloudinary.UploadLarge(uploadParams, TEST_CHUNK_SIZE);
593598

594-
AssertUploadLarge(result, largeFileLength);
599+
AssertUploadLarge(result);
595600
}
596601

597602
[Test, RetryWithDelay]
598603
public async Task TestUploadLargeRawFilesAsyncInParallel()
599604
{
600605
// support asynchronous uploading large raw files
601606
var largeFilePath = m_testLargeImagePath;
602-
int largeFileLength = (int)new FileInfo(largeFilePath).Length;
603607

604608
var uploadParams = GetUploadLargeRawParams(largeFilePath);
605609

606610
var result = await m_cloudinary.UploadLargeAsync<RawUploadResult>(uploadParams, TEST_CHUNK_SIZE, 2);
607611

608-
AssertUploadLarge(result, largeFileLength);
612+
AssertUploadLarge(result);
609613
}
610614

611615
private RawUploadParams GetUploadLargeRawParams(string path)
@@ -617,54 +621,53 @@ private RawUploadParams GetUploadLargeRawParams(string path)
617621
};
618622
}
619623

620-
private void AssertUploadLarge(RawUploadResult result, int fileLength)
624+
private void AssertUploadLarge(RawUploadResult result, int fileLength = 0, string etag = null)
621625
{
626+
if (fileLength == 0)
627+
{
628+
fileLength = m_largeFileLength;
629+
}
630+
if (etag == null)
631+
{
632+
etag = m_largeFileEtag;
633+
}
622634
Assert.NotNull(result);
623635
Assert.AreEqual(fileLength, result.Bytes, result.Error?.Message);
636+
Assert.AreEqual(etag, result.Etag, result.Error?.Message);
624637
}
625638

626639
[Test, RetryWithDelay]
627640
public void TestUploadLarge()
628641
{
629642
// support uploading large image
630-
631-
var largeFilePath = m_testLargeImagePath;
632-
int fileLength = (int)new FileInfo(largeFilePath).Length;
633643
var result = m_cloudinary.UploadLarge(new ImageUploadParams()
634644
{
635-
File = new FileDescription(largeFilePath),
645+
File = new FileDescription(m_testLargeImagePath),
636646
Tags = m_apiTag
637647
}, TEST_CHUNK_SIZE);
638648

639-
Assert.AreEqual(fileLength, result.Bytes, result.Error?.Message);
649+
AssertUploadLarge(result);
640650
}
641651

642652
[Test, RetryWithDelay]
643653
public async Task TestUploadLargeAutoFilesAsync()
644654
{
645-
// support asynchronous uploading large raw files
646-
var largeFilePath = m_testLargeImagePath;
647-
int largeFileLength = (int)new FileInfo(largeFilePath).Length;
648-
649655
var uploadParams = new AutoUploadParams()
650656
{
651-
File = new FileDescription(largeFilePath),
657+
File = new FileDescription(m_testLargeImagePath),
652658
Tags = m_apiTag
653659
};
654660

655661
var result = await m_cloudinary.UploadLargeAsync(uploadParams, TEST_CHUNK_SIZE);
656662

657-
AssertUploadLarge(result, largeFileLength);
663+
AssertUploadLarge(result);
658664

659665
Assert.AreEqual("image", result.ResourceType);
660666
}
661667

662668
[Test, RetryWithDelay]
663669
public void TestUploadChunkSingleStream()
664670
{
665-
var largeFilePath = m_testLargeImagePath;
666-
var largeFileLength = (int)new FileInfo(largeFilePath).Length;
667-
668671
ImageUploadResult result = null;
669672

670673
using (var currChunk = new MemoryStream())
@@ -677,7 +680,7 @@ public void TestUploadChunkSingleStream()
677680

678681
var buffer = new byte[TEST_CHUNK_SIZE];
679682

680-
using (var source = File.Open(largeFilePath, FileMode.Open))
683+
using (var source = File.Open(m_testLargeImagePath, FileMode.Open))
681684
{
682685
int read;
683686
while ((read = source.Read(buffer, 0, buffer.Length)) > 0)
@@ -693,16 +696,13 @@ public void TestUploadChunkSingleStream()
693696
}
694697
}
695698

696-
AssertUploadLarge(result, largeFileLength);
699+
AssertUploadLarge(result);
697700
Assert.AreEqual("image", result?.ResourceType);
698701
}
699702

700703
[Test, RetryWithDelay]
701704
public async Task TestUploadChunkMultipleStreamsCustomOffsetAsync()
702705
{
703-
var largeFilePath = m_testLargeImagePath;
704-
var largeFileLength = (int)new FileInfo(largeFilePath).Length;
705-
706706
ImageUploadResult result = null;
707707

708708
var uploadParams = new ImageUploadParams()
@@ -714,7 +714,7 @@ public async Task TestUploadChunkMultipleStreamsCustomOffsetAsync()
714714

715715
var buffer = new byte[TEST_CHUNK_SIZE];
716716

717-
using (var source = File.Open(largeFilePath, FileMode.Open))
717+
using (var source = File.Open(m_testLargeImagePath, FileMode.Open))
718718
{
719719
int read;
720720
while ((read = source.Read(buffer, 0, buffer.Length)) > 0)
@@ -727,19 +727,16 @@ public async Task TestUploadChunkMultipleStreamsCustomOffsetAsync()
727727
}
728728
}
729729

730-
AssertUploadLarge(result, largeFileLength);
730+
AssertUploadLarge(result);
731731
Assert.AreEqual("image", result?.ResourceType);
732732
}
733733

734734
[Test, RetryWithDelay]
735735
public void TestUploadChunkMultipleFileParts()
736736
{
737-
var largeFilePath = m_testLargeImagePath;
738-
var largeFileLength = (int)new FileInfo(largeFilePath).Length;
739-
740737
ImageUploadResult result = null;
741738

742-
var fileChunks = SplitFile(largeFilePath, TEST_CHUNK_SIZE, "multiple");
739+
var fileChunks = SplitFile(m_testLargeImagePath, TEST_CHUNK_SIZE, "multiple");
743740

744741
var uploadParams = new ImageUploadParams()
745742
{
@@ -773,17 +770,14 @@ public void TestUploadChunkMultipleFileParts()
773770
}
774771
}
775772

776-
AssertUploadLarge(result, largeFileLength);
773+
AssertUploadLarge(result);
777774
Assert.AreEqual("image", result?.ResourceType);
778775
}
779776

780777
[Test, RetryWithDelay]
781778
public void TestUploadChunkMultipleFilePartsInParallel()
782779
{
783-
var largeFilePath = m_testLargeImagePath;
784-
var largeFileLength = (int)new FileInfo(largeFilePath).Length;
785-
786-
var fileChunks = SplitFile(largeFilePath, TEST_CHUNK_SIZE, "multiple_parallel");
780+
var fileChunks = SplitFile(m_testLargeImagePath, TEST_CHUNK_SIZE, "multiple_parallel");
787781

788782
var uploadParams = new RawUploadParams()
789783
{
@@ -820,7 +814,7 @@ public void TestUploadChunkMultipleFilePartsInParallel()
820814

821815
var uploadResult = resultCollection.FirstOrDefault(r => r.AssetId != null);
822816

823-
AssertUploadLarge(uploadResult, largeFileLength);
817+
AssertUploadLarge(uploadResult);
824818
Assert.AreEqual("raw", uploadResult?.ResourceType);
825819
}
826820

CloudinaryDotNet/Core/LimitedStream.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ internal class LimitedStream : Stream
1212
private readonly Stream originalStream;
1313
private long remainingBytes;
1414
private long startOffset;
15+
private long currOffset;
1516

1617
/// <summary>
1718
/// Initializes a new instance of the <see cref="LimitedStream"/> class.
@@ -24,7 +25,7 @@ public LimitedStream(Stream stream, long offset, long maxBytes)
2425
{
2526
originalStream = stream ?? throw new ArgumentNullException(nameof(stream));
2627
remainingBytes = maxBytes;
27-
startOffset = offset;
28+
startOffset = currOffset = offset;
2829

2930
if (!stream.CanSeek)
3031
{
@@ -64,9 +65,11 @@ public override long Position
6465
public override int Read(byte[] buffer, int offset, int count)
6566
{
6667
// make sure stream is not moved around.
67-
originalStream.Seek(startOffset, SeekOrigin.Begin);
68+
originalStream.Seek(currOffset, SeekOrigin.Begin);
6869

6970
var bytesRead = originalStream.Read(buffer, offset, (int)Math.Min(count, remainingBytes));
71+
72+
currOffset += bytesRead;
7073
remainingBytes -= bytesRead;
7174

7275
return bytesRead;

0 commit comments

Comments
 (0)