【问题标题】:Make a get api that returns a BLOB .net core (EF)制作一个返回 BLOB .net 核心 (EF) 的 get api
【发布时间】:2020-05-16 21:03:46
【问题描述】:

我有一个数据库,其中包含一个具有 id 和 BLOB 的表。 我想要的是获取blob并基本上将其流式传输到客户端, 而不是在内存中检索它。那是因为 blob 可能非常大(100 MB)。

我几乎已经使用 SQLdataReader 实现了这一点。 这样做,当我发出获取请求时,它会立即开始下载,并且没有内存开销。这是使用.net core 2.2 但是,当我切换到 .net core 3.1 时,它现在不起作用,内存被 100 兆字节填满。我也想使用实体框架来达到同样的效果,但到目前为止我还没有找到任何好的在线资源。

这是我到现在为止的代码。

[HttpGet]
    public  IEnumerable<Byte[]> GetStreaming()
    {

        var header = Request.Headers["Accept-Encoding"];
        System.Console.WriteLine(header);

        string connectionString = "Data Source=myPc\\SQLEXPRESS;Initial Catalog=dbo;Persist Security Info=True;User ID=sa;Password=admin";

        //----------------------
        SqlConnection connection = new SqlConnection(connectionString);

        connection.Open();

        SqlCommand command = new SqlCommand("exec getBlob", connection);

        SqlTransaction tran = connection.BeginTransaction(IsolationLevel.ReadCommitted);
        command.Transaction = tran;
        byte[] buffer = new byte[5000000];
        long position = 0;
        long bytesRead = 5000000;
        using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
        {
            reader.Read();
            reader.GetBytes(0, position, null, 0, 5000000);
            while (bytesRead == 5000000)
            {
                // Get the pointer for file
                bytesRead = reader.GetBytes(0, position, buffer, 0, 5000000);
                position += bytesRead;
                yield return buffer;

                // Create the SqlFileStream

            }

        }

    }

我试过就这样做

        public  IEnumerable<byte[]> DownloadFile()
    {

        yield return  context.t_noFs.Where(u => u.Id == 1)
            .Select(u => u.dat).
            FirstOrDefault();
    }

虽然这确实返回了一个值,但它没有达到预期的效果并填满了内存。

【问题讨论】:

    标签: c# .net entity-framework .net-core ef-core-3.0


    【解决方案1】:

    在您的情况下,最佳做法是使用流。

    [HttpGet]
    public  FileStreamResult GetStreaming()
    {
        var header = Request.Headers["Accept-Encoding"];
        System.Console.WriteLine(header);
    
        string connectionString = "Data Source=myPc\\SQLEXPRESS;Initial Catalog=dbo;Persist Security Info=True;User ID=sa;Password=admin";
    
        //----------------------
        SqlConnection connection = new SqlConnection(connectionString);
    
        connection.Open();
    
        SqlCommand command = new SqlCommand("exec getBlob", connection);
    
        SqlTransaction tran = connection.BeginTransaction(IsolationLevel.ReadCommitted);
        command.Transaction = tran;
        SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess)
        var blobStream = reader.GetStream(0);
    
        return new FileStreamResult(blobStream, "application/x-binary")
        {
             FileDownloadName = "your file name"
        };
    }
    

    【讨论】:

    • 我收到了一个内部服务器错误。是否有一些我没有提供的其他信息可能是这个问题的罪魁祸首?这是否需要最新版本的 .net core 和 EF?
    • 您得到的确切异常是什么?
    • 表示无法访问已处理的对象。我从 SqlDataReader 周围删除了 using (),现在它下载了文件
    • 可能是,我没有测试它只是一个应该如何使用它的例子。但我会更新它。
    • 您需要延迟 SqlDataReader 和 SqlConnection 上的 Dispose() 直到请求结束。添加Response.RegisterForDispose(reader); 和Response.RegisterForDispose(connection); 提前释放会报错,不释放会导致连接泄漏。
    猜你喜欢
    • 1970-01-01
    • 2021-09-19
    • 1970-01-01
    • 1970-01-01
    • 2020-04-09
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    • 2021-05-21
    相关资源
    最近更新 更多