【发布时间】:2021-09-06 07:15:44
【问题描述】:
我想将文件上传到 SQL Server 数据库并从 Web 浏览器再次下载(任何文件:xlsx、pdf 等)。
这是我的 HTML 标记:
<input type="file" class="form-control-file" id="fileupload1" onchange="showname()" />
Javascript 转换为二进制:
var filename;
var contentType;
var filestream;
var fixarray;
const fileByteArray = [];
function showname() {
var name = document.getElementById('fileupload1');
filename = name.files.item(0).name;
contentType = name.files.item(0).type;
var reader = new FileReader();
reader.readAsArrayBuffer(name.files[0]);
reader.onload = function () {
filestream = reader.result;
fixarray = new Uint8Array(filestream);
for (let i = 0; i < fixarray.length; i++) {
fileByteArray.push(fixarray[i]);
}
};
}
我的 AJAX 调用(从其他函数成功调用 events.id):
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
url: "confirmationcomplete.aspx/finish",
data: '{ id: ' + JSON.stringify(events.id) + ',contentType: "' + contentType + '",name: "' + filename + '",binaryy: "' + fileByteArray + '"}',
success: function (data) {
alert('Success upload');
},
error: function (xhr, status, error) {
alert(xhr.responseText);
}
})
后端代码(C#):
[WebMethod]
public static void finish(int id, string contentType, string name, string binaryy)
{
string str = @"Data Source=172.16.111.45\SQLEXPRESS;Initial Catalog=dashboard;User ID=sa;Password=sdfgh";
SqlConnection cn2 = new SqlConnection(str);
SqlCommand cmd7 = new SqlCommand("[sp_uploadfile]", cn2);
cmd7.Parameters.Add("@eventID", SqlDbType.Int);
cmd7.Parameters["@eventID"].Value = id;
cmd7.Parameters.Add("@contentType", SqlDbType.VarChar);
cmd7.Parameters["@contentType"].Value = contentType;
cmd7.Parameters.Add("@name", SqlDbType.VarChar);
cmd7.Parameters["@name"].Value = name;
byte[] byteArray = Encoding.UTF8.GetBytes(binaryy);
cmd7.Parameters.Add("@byte", SqlDbType.VarBinary,-1);
cmd7.Parameters["@byte"].Value = byteArray;
cmd7.CommandType = CommandType.StoredProcedure;
try
{
cn2.Open();
cmd7.ExecuteNonQuery();
cn2.Close();
}
catch (Exception ex)
{
}
}
存储过程:
CREATE PROCEDURE [dbo].[sp_uploadfile]
@eventID int,
@contentType varchar(255),
@name varchar(255),
@byte varbinary(MAX)
AS
BEGIN
INSERT INTO eventsScheduler
VALUES (@eventID, @contentType, @name, @byte)
END
从我上面的所有代码中,上传文件到 SQL Server 数据库的过程是成功的。
但是当我尝试从浏览器下载它时,它会抛出一个错误
Excel 无法打开文件...因为文件格式或扩展名无效
按钮下载:
<asp:LinkButton runat="server" ID="btndownload" OnClick="DownloadFile" CommandArgument="<%#hdID%>">Download Report</asp:LinkButton>
这是我的下载代码:
protected void DownloadFile(object sender, EventArgs e)
{
int a = Convert.ToInt32(hdID.Value);
byte[] bytes;
string contentType, fileName;
string constr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "select EventID,contentType,filename, report from [eventsScheduler] where EventID=@id";
cmd.Parameters.AddWithValue("@id", a);
cmd.Connection = con;
con.Open();
using (SqlDataReader sdr = cmd.ExecuteReader())
{
sdr.Read();
bytes = (byte[])sdr["report"];
contentType = sdr["contentType"].ToString();
fileName = sdr["filename"].ToString();
}
con.Close();
}
}
if (bytes.Length != 0)
{
Response.Clear();
Response.Buffer = true;
Response.Charset = "";
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = contentType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName);
Response.BinaryWrite(bytes);
Response.Flush();
Response.End();
}
else
{
}
}
我认为问题在于将二进制文件从文件上传转换为 javascript 代码。
所以我正在尝试创建一个新的上传控件(使用 asp 控件)并尝试直接上传文件:
ASP 控制:
<asp:FileUpload ID="fileUpload_NewProblem" runat="server" Width="100%" />
按钮上传:
<asp:LinkButton runat="server" OnClick="Unnamed_Click">Upload</asp:LinkButton>
按钮操作:
protected void Unnamed_Click(object sender, EventArgs e)
{
uploadFile();
}
后端代码:
public void uploadFile()
{
id = Convert.ToInt32(Request["id"]);
int ids = id; // int.Parse((sender as LinkButton).CommandArgument);
string filename = Path.GetFileName(fileUpload_NewProblem.PostedFile.FileName);
string contentType = fileUpload_NewProblem.PostedFile.ContentType;
using (Stream fs = fileUpload_NewProblem.PostedFile.InputStream)
{
using (BinaryReader br = new BinaryReader(fs))
{
byte[] bytes = br.ReadBytes((Int32)fs.Length);
string constr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
string query = " INSERT INTO eventsScheduler VALUES (@eventID,@contentType,@name,@byte )";
using (SqlCommand cmd = new SqlCommand(query))
{
cmd.Connection = con;
cmd.Parameters.AddWithValue("@eventID", ids);
cmd.Parameters.AddWithValue("@name", filename);
cmd.Parameters.AddWithValue("@contentType", contentType);
cmd.Parameters.AddWithValue("@byte", bytes);
try
{
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception ex)
{
}
}
}
}
}
}
当我使用第二种方法(不使用 AJAX)上传文件时,我使用相同的下载代码成功下载了文件。
我的问题是:如何以与 C# 相同的方式使用 javascript 将文件转换为二进制文件?
【问题讨论】:
-
注意:您并没有真正“转换”文件,您只是从中提取字节。但是你为什么要使用 JavaScript 来做到这一点呢?以 HTTP 期望的方式上传它要容易得多。不要增加额外的复杂性。
-
如果你想知道如何使用jQuery AJAX上传文件,网上已经有很多例子了,比你的方法简单得多
-
旁注:您应该不为您的存储过程使用
sp_前缀。微软有reserved that prefix for its own use (see Naming Stored Procedures),你确实会在未来某个时候冒着名称冲突的风险。 It's also bad for your stored procedure performance。最好只是简单地避免sp_并使用其他东西作为前缀 - 或者根本不使用前缀! -
谢谢@marc_s。我删除了我所有的 sp_ 前缀。
标签: javascript c#