问题
I have been asked to create a web site in Visual Studio 2010 using C#, where I need to upload, download and play video files, a lot like youtube. I have done the uploading part, but I just can't get the downloading and playing the video from the database part. Here is the code, I have been using on the page where download and playing will take place:
Table details:
Vid_Id (int), Video_Name (nvarchar), Video (VarBinary), Video_Size(bigint), Added (nvarchar)
Default.aspx
<asp:Panel ID="Panel1" runat="server" Height="363px">
<asp:DataList ID="Repeater1" runat="server" DataSourceID="dsvidz">
<ItemTemplate>
<video id="player" height="300" width="300" controls autoplay>
<source src='<%# "VideoHandler.ashx?id=" + Eval("Vid_Id") + "&type=mp4" %>' type='video/mp4'/>
</video>
</ItemTemplate>
</asp:DataList>
</asp:Panel>
<asp:Button ID="Button1" runat="server" Text="Download Video"
onclick="Button1_Click" Enabled="False" />
Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections;
using System.Configuration;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Data;
using System.Web.Security;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls.WebParts;
public partial class Default : System.Web.UI.Page
{
SqlConnection connection = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\ASPNETDB.MDF;Integrated Security=True;User Instance=True");
private int id = 0, index=0;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
BindData();
}
private DataTable GetSpecificVideo(object i)
//pass the id of the video
{
SqlDataAdapter adapter = new SqlDataAdapter("SELECT Video, Vid_Id " + "FROM Vid_Dir WHERE Vid_Id = @id", connection);
adapter.SelectCommand.Parameters.Add("@id", SqlDbType.Int).Value = (int)i;
DataTable table = new DataTable();
adapter.Fill(table);
return table;
}
void BindData()
{
//hfSearchText has the search string returned from the grid.
if (hfSearchText.Value != "")
dsvidz.SelectCommand += " where " + hfSearchText.Value;
DataView dv = (DataView)dsvidz.Select(new DataSourceSelectArguments());
//hfSort has the sort string returned from the grid.
if (hfSort.Value != "")
dv.Sort = hfSort.Value;
GridView1.DataSource = dv;
try
{
GridView1.DataBind();
}
catch (Exception exp)
{
//If databinding threw exception bcoz current page index is > than available page index
GridView1.PageIndex = 0;
GridView1.DataBind();
}
finally
{
//Select the first row returned
if (GridView1.Rows.Count > 0)
GridView1.SelectedIndex = 0;
}
}
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "play")
{
this.index = Convert.ToInt32(e.CommandArgument);
GridViewRow row = GridView1.Rows[this.index];
SqlCommand cmd1 = new SqlCommand("SELECT Vid_Id FROM Vid_Dir WHERE Video_Name=@VN", connection);
SqlDataReader idRdr = null;
idRdr = cmd1.ExecuteReader();
while (idRdr.Read())
{
this.id = Convert.ToInt32(idRdr["Vid_Id"]);
Label1.Text = Convert.ToString(idRdr["Video_Name"]);
Label3.Text = Convert.ToString(idRdr["Added"]);
Label5.Text = Convert.ToString(idRdr["Description"]);
}
Repeater1.DataSource = GetSpecificVideo(this.id);
Repeater1.DataBind();
Button1.Enabled=true;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
DataTable file = GetAFile(this.id);
DataRow row = file.Rows[this.index];
string name = (string)row["Video_Name"];
Byte[] data = (Byte[])row["Video"];
// Send the file to the browser
Response.AddHeader("Content-type", "video/mp4");
Response.AddHeader("Content-Disposition", "attachment; filename=" + name);
Response.BinaryWrite(data);
Response.Flush();
Response.End();
}
public static DataTable GetAFile(int i)
{
DataTable file = new DataTable();
using (SqlConnection connection = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\ASPNETDB.MDF;Integrated Security=True;User Instance=True"))
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandTimeout = 0;
cmd.CommandText = "SELECT Vid_Id, Video_Name, Video_Size FROM Vid_Dir " + "WHERE Vid_Id=@ID";
cmd.CommandType = CommandType.Text;
SqlDataAdapter adapter = new SqlDataAdapter();
cmd.Parameters.Add("@ID", SqlDbType.Int);
cmd.Parameters["@ID"].Value = i;
adapter.SelectCommand = cmd;
adapter.Fill(file);
connection.Close();
}
return file;
}
}
VideoHandler.ashx
<%@ WebHandler Language="C#" Class="VideoHandler" %>
using System;
using System.Web;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Data;
public class VideoHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
SqlConnection connection = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\ASPNETDB.MDF;Integrated Security=True;User Instance=True");
SqlCommand cmd = new SqlCommand("SELECT Video, Video_Name" + " FROM Vid_Dir WHERE Vid_Id = @id", connection);
cmd.Parameters.Add("@id", SqlDbType.Int).Value =context.Request.QueryString["id"];
try
{
connection.Open();
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.Default);
if (reader.HasRows)
{
while (reader.Read())
{
context.Response.ContentType = reader["Video_Name"].ToString();
context.Response.BinaryWrite((byte[])reader["Video"]);
}
}
}
finally
{
connection.Close();
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
The HTML5 Video tag which got used here is showing error message that is:
Invalid Source
But when, I'm copying the url from the player by right-clicking on it during runtime, then pasting it on the browser address bar and pressing enter, it's starting to download the video with the name
Video Handler.mp4
Plus it's showing the same number of video players as many videos are uploaded in the database. Can anyone please help me..? Thank you
回答1:
You're almost there. Here is the GIST: Grab the bytes from SQL Server and write it to the response stream.
You should also set the ContentType of the response (assuming that you know it's mp4 of course):
context.Response.ContentType = "video/mp4";
This line tells the browser that it is a mp4 file, so you can embed the video in a tag in html5 or open a video player etc.
Well, storing video files and retrieving them in a DB like this is not a really good practice, but if your purpose is to do a school assignment or something like that, it will work.
来源:https://stackoverflow.com/questions/20173448/retrieve-video-file-stored-as-varbinary-in-sql-server-express-database