Я знаю, что название длинное, но оно точно описывает проблему.Я не знал, как еще это объяснить, потому что это полностью там.
У меня есть утилита, написанная на C # для .NET Core 2.1, которая загружает и дешифрует файлы (шифрование AES), изначально загруженные нашими клиентами изнаше зашифрованное хранилище, поэтому они могут быть повторно обработаны через некоторые из наших служб в случае их отказа.Эта утилита запускается через CLI, используя идентификаторы базы данных для файлов в качестве аргументов, например, download.bat 101 102 103
загрузит 3 файла с соответствующими идентификаторами.Я получаю байтовые данные через очередь сообщений (на самом деле не намного больше, чем сокет TCP), которая описывает изображение .TIF.
У меня есть веская причина полагать, что байтовые данные никогда не повреждаются насервер.Причина в том, что когда я запускаю утилиту только с одним параметром ID, таким как download.bat 101
, она работает просто отлично.Кроме того, когда я запускаю его с несколькими идентификаторами, последний загруженный утилитой файл всегда остается без изменений, а остальные всегда повреждены.
Это странное поведение сохраняется в двух разных реализациях для записи байтовых данных в файл.Эти реализации приведены ниже.
File.ReadAllBytes
реализация:
private static void WriteMessageContents(FileServiceResponseEnvelope envelope, string destination, byte[] encryptionKey, byte[] macInitialVector)
{
using (var inputStream = new MemoryStream(envelope.Payload))
using (var outputStream = new MemoryStream(envelope.Payload.Length))
{
var sha512 = YellowAesEncryptor.DecryptStream(inputStream, outputStream, encryptionKey, macInitialVector, 0);
File.WriteAllBytes(destination, outputStream.ToArray());
_logger.LogStatement($"Finished writing [{envelope.Payload.Length} bytes] to [{destination}].", LogLevel.Debug);
}
}
FileStream
реализация:
private static void WriteMessageContents(FileServiceResponseEnvelope envelope, string destination, byte[] encryptionKey, byte[] macInitialVector)
{
using (var inputStream = new MemoryStream(envelope.Payload))
using (var outputStream = new MemoryStream(envelope.Payload.Length))
{
var sha512 = YellowAesEncryptor.DecryptStream(inputStream, outputStream, encryptionKey, macInitialVector, 0);
using (FileStream fs = new FileStream(destination, FileMode.Create))
{
var bytes = outputStream.ToArray();
fs.Write(bytes, 0, envelope.Payload.Length);
_logger.LogStatement($"File byte content: [{string.Join(", ", bytes.Take(16))}]", LogLevel.Trace);
fs.Flush();
}
_logger.LogStatement($"Finished writing [{envelope.Payload.Length} bytes] to [{destination}].", LogLevel.Debug);
}
}
Этот метод вызывается из цикла for, который сначала получаетсообщения, которые я описал ранее, а затем передают свои полезные данные вышеуказанному методу:
using (var requestSocket = new RequestSocket(fileServiceEndpoint))
{
// Envelopes is constructed beforehand
foreach (var envelope in envelopes)
{
var timer = Stopwatch.StartNew();
requestSocket.SendMoreFrame(messageTypeBytes);
requestSocket.SendMoreFrame(SerializationHelper.SerializeObjectToBuffer(envelope));
if (!requestSocket.TrySendFrame(_timeout, signedPayloadBytes, signedPayloadBytes.Length))
{
var message = $"Timeout exceeded while processing [{envelope.ActionType}] request.";
_logger.LogStatement(message, LogLevel.Error);
throw new Exception(message);
}
var responseReceived = requestSocket.TryReceiveFrameBytes(_timeout, out byte[] responseBytes);
...
var responseEnvelope = SerializationHelper.DeserializeObject<FileServiceResponseEnvelope>(responseBytes);
...
_logger.LogStatement($"Received response with payload of [{responseEnvelope.Payload.Length} bytes].", LogLevel.Info);
var destDir = downloadDetails.GetDestinationPath(responseEnvelope.FileId);
if (!Directory.Exists(destDir))
Directory.CreateDirectory(destDir);
var dest = Path.Combine(destDir, idsToFileNames[responseEnvelope.FileId]);
WriteMessageContents(responseEnvelope, dest, encryptionKey, macInitialVector);
}
}
Я также знаю, что TIF-файлы имеют очень специфический заголовок, который выглядит примерно так в необработанных байтах:
[73, 73, 42, 0, 8, 0, 0, 0, 20, 0...
Он всегда начинается с «II» (73, 73) или «ММ» (77, 77), за которым следует 42 (вероятно, ссылка автостопщика).Я проанализировал байты, написанные утилитой.Последний файл всегда имеет заголовок, который похож на этот.Остальные всегда случайные байты;казалось бы перемешанные или неправильно упорядоченные двоичные данные изображения.Любое понимание этого было бы очень ценно, потому что я не могу сосредоточиться на том, что мне даже нужно сделать, чтобы диагностировать это.
ОБНОВЛЕНИЕ
Я смогчтобы выяснить эту проблему с помощью elgonzo
в комментариях.Иногда помогает не прямой ответ, а кто-то ковыряет в голове, пока вы не посмотрите в нужном месте.