Считайте большой файл в байтовый массив и закодируйте его в ToBase64String - PullRequest
0 голосов
/ 10 сентября 2018

Я реализовал POC для чтения всего содержимого файла в массиве Byte []. Теперь мне удалось прочитать файлы, размер которых меньше 100 МБ, когда я загружаю файл размером более 100 МБ, он выдает

Convert.ToBase64String (mybytearray) Невозможно получить значение локальная переменная или аргумент, потому что недостаточно памяти имеется.

Ниже приведен мой код, который я пытался прочитать из файла в массив байтов

var sFile = fileName;
var mybytearray = File.ReadAllBytes(sFile);

var binaryModel = new BinaryModel
{
    fileName = binaryFile.FileName,
    binaryData = Convert.ToBase64String(mybytearray),
    filePath = string.Empty
};

Мой класс модели такой, как показано ниже

public class BinaryModel
{
    public string fileName { get; set; }
    public string binaryData { get; set; }
    public string filePath { get; set; }
}

Я получаю сообщение: «Convert.ToBase64String (mybytearray) Невозможно получить значение локальной переменной или аргумента, так как недостаточно памяти». эта ошибка в Convert.ToBase64String (mybytearray).

Есть ли что-нибудь, что мне нужно позаботиться, чтобы предотвратить эту ошибку?

Примечание. Я не хочу добавлять разрывы строк в содержимое моего файла

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Я бы использовал два файловых потока - один для чтения большого файла, другой для записи результата обратно.

Таким образом, в блоках вы должны преобразовать в базу 64 ... затем преобразовать полученную строку в байты ... и записать.

    private static void ConvertLargeFileToBase64()
    {
        var buffer = new byte[16 * 1024];
        using (var fsIn = new FileStream("D:\\in.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            using (var fsOut = new FileStream("D:\\out.txt", FileMode.CreateNew, FileAccess.Write))
            {
                int read;
                while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
                {
                    // convert to base 64 and convert to bytes for writing back to file
                    var b64 = Encoding.ASCII.GetBytes(Convert.ToBase64String(buffer));

                    // write to the output filestream
                    fsOut.Write(b64, 0, read);
                }

                fsOut.Close();
            }
        }
    }
0 голосов
/ 10 сентября 2018

Для экономии памяти вы можете конвертировать поток байтов в 3 пакета. Каждые три байта выдают 4 байта в Base64. Вам не нужен весь файл в памяти сразу.

Вот псевдокод:

Repeat
1. Try to read max 3 bytes from stream
2. Convert to base64, write to output stream

И простая реализация:

using (var inStream = File.OpenRead("E:\\Temp\\File.xml"))
using (var outStream = File.CreateText("E:\\Temp\\File.base64"))
{
    var buffer = new byte[3];
    int read;
    while ((read = inStream.Read(buffer, 0, 3)) > 0)
    {
        var base64 = Convert.ToBase64String(buffer, 0, read);
        outStream.Write(base64);
    }
}

Подсказка: допустимо каждое умножение на 3. Выше - больше памяти, лучше производительность, меньше - меньше памяти, хуже производительность.

Дополнительная информация:

Файловый поток является примером. В результате поток использует [HttpContext].Response.OutputStream и пишет прямо в него. Обработка сотен мегабайт в одном блоке убьет вас и ваш сервер.

Подумайте об общих требованиях к памяти. 100 МБ в строке приводит к 133 МБ в байтовом массиве, так как вы писали о модели, я ожидаю копию этого 133 МБ в ответ. И помните, это просто простая просьба. Несколько таких запросов могут истощить вашу память.

...