sql - Angular 8 上传图像文件(jpg 等) - 第二种方法
问题描述
我想将 Angular 8 与 Asp.Net Web Api 一起使用来上传图像文件并将其存储到 SQL Server 数据库表中,其中图像列定义为 varbinary(max)。
注意:我可以使用 ASP.Net Web 表单来做到这一点 - 它添加了图像,我可以相应地显示它。(我在下面添加了图像代码)。所以我试图模仿网络表单上传,但使用 Angular 作为前端。
为了在 Angular 8 中上传文件,我使用了以下建议:https ://www.academind.com/learn/angular/snippets/angular-image-upload-made-easy/
我将选定的图像文件作为二进制文件发送到 Web Api。
单击按钮后,我在服务器端收到错误消息。http://localhost:50454/Api/Image/AddImage/的 Http 失败响应:500 内部服务器错误。身体是:[对象对象]
我能够使选定的图像文件出现在页面上。
这是所有的代码。注意:为简单起见,并未包含所有代码。
我的 SQL 服务器表定义 - 其中图像被定义为 varbinary:
CREATE TABLE [dbo].[tblImages]
(
[ImageId] [int] IDENTITY(1,1) NOT NULL,
[ImageData] [varbinary](max) NOT NULL
CONSTRAINT [PK_Image] PRIMARY KEY CLUSTERED
(
[ImageId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
我的 SQL 服务器插入存储过程:
CREATE procedure [dbo].[InsertImages]
@ImageData varbinary(max)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.tblImages (
ImageData )
VALUES (
@ImageData )
RETURN 0
END
角 html:
<input type="file" (change)="onFileChanged($event)">
<img [src]="imgURL" height="200" *ngIf="imgURL">
Angular 组件方法代码:
onFileChanged(event) {
// Get the file selected.
const selectedFile = event.target.files[0];
// To display the selected image before deciding to upload it.
let reader = new FileReader();
// Gets a 'base64' representation of an image.
reader.readAsDataURL(event.target.files[0]);
reader.onload = (event2) => {
// Sets the html <img> tag to the image.
this.imgURL = reader.result;
};
// Call the service to use the web api to add the image to the database.
this.imageService.addImage(selectedFile).subscribe(
event => {
console.log(event);
});
}
我的 Angular Image 服务方法:
private data: any;
// The Asp.Net Web Api endpoint.
url = "http://localhost:50454/Api/Image";
addImage(image: Image): Observable<Image> {
const httpOptions = {
headers: new HttpHeaders({ "Content-Type": "application/json" })
};
// Call the ASP.NET 2.1 MVC Web API.
return this.http
.post<Image>(this.url + "/AddImage/", image, httpOptions)
.pipe(
tap(data => data),
catchError(this.handleError)
);
}
我的角度模型类:
export class Image {
ImageData: Binary[]; <--- Is this correct?
}
我的 Asp.Net Web Api 数据模型:
namespace PrototypeWebApi2.Models
{
public class Image
{
public byte[] ImageData { get; set; } <--- Is this correct?
}
}
我的 Asp.Net Web Api 方法:
[HttpPost]
[Route("AddImage")]
public IHttpActionResult PostImage(Image data)
{
try
{
return Ok(dataaccesslayer.AddImage(data));
}
catch (Exception)
{
throw;
}
}
我的 Asp.Net Web Api 数据访问层方法:
public int AddImage(Image image)
{
try
{
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand("InsertImages", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("@ImageData", image.ImageData);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
return 1;
}
catch
{
throw;
}
}
我的 Asp.Net Web 表单代码可以上传图像文件并且工作正常:
HTML:
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="AdminPage.aspx.cs" Inherits="Media.Admin.AdminPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<h1>Administration</h1>
<hr />
<h3>Add Image:</h3>
<table>
<tr>
<td><asp:Label ID="LabelAddImageFile" runat="server">Image File:</asp:Label></td>
<td>
<asp:FileUpload ID="MediaUploadFile" runat="server" />
<asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" Text="* Image file path required." ControlToValidate="MediaUploadFile" SetFocusOnError="true" Display="Dynamic"></asp:RequiredFieldValidator>
</td>
</tr>
</table>
<p></p>
<asp:Button ID="AddMediaButton" runat="server" Text="Add Media" OnClick="AddMediaButton_Click" CausesValidation="true" CssClass="btn btn-primary"/>
<asp:Label ID="LabelAddStatus" runat="server" Text=""></asp:Label>
<p></p>
</asp:Content>
后面的代码:
protected void AddMediaButton_Click(object sender, EventArgs e)
{
string strErrorMessage = "";
string fileExtension = "";
int fileSize = 0;
Boolean fileOK = false;
// Get the image file that was selected. References the ASP.Net control.
HttpPostedFile postedFile = MediaUploadFile.PostedFile;
fileExtension = Path.GetExtension(fileName).ToLower();
....
if (fileOK)
{
Stream stream = postedFile.InputStream;
BinaryReader binaryReader = new BinaryReader(stream);
// Read the file into a array of bytes.
Byte[] bytes = binaryReader.ReadBytes((int)stream.Length);
try
{
....
cmd.Parameters.Add("@ImageData", SqlDbType.VarBinary).Value = bytes;
cmd.ExecuteNonQuery();
.....
}
catch (Exception ex)
{
}
finally
{
dbFunc.CloseDB();
}
}
else
{
....
}
}
解决方案
您从中提取的对象类型event.target.files[0]
是,File
但是您将其传递给addImage
需要类型的函数Image
。我猜它假设是any
这样 Typescript 不会捕捉到不匹配的情况。
接下来,在将文件发布到服务器时,我总是使用FormData
对象获得更好的成功。
uploadFiles(files: File[]) {
const formData = new FormData();
files.forEach(file => {
formData.append(file.name, file, file.name);
});
return this.http.post(`/api/files`, formData);
}
Angular 的 HttpClient 服务会自动为此设置Content-Type: multipart/form-data
标头。
然后在 WebApi 端,我System.Web.HttpContext.Current.Request.Files
用来访问实际的文件二进制文件。从那里你应该能够使用某种形式IO.Stream
来保存文件。
希望这可以帮助!
推荐阅读
- xml - Powershell 将 CSV 导出为 XML
- soap - Web 服务能否同时支持 SOAP 1.1 和 1.2
- android - Cordova Angular webView 错误拒绝应用内联样式,因为它违反了以下内容安全策略指令
- google-cloud-platform - 跨区域 GKE 主节点访问
- javascript - 如何在 JS 中将变量放入 Json Array 函数中
- image-processing - 使用 imagemagick 将 GIF 图像转换为 PNG,但得到的是 RGBA 图像而不是调色板版本
- ios - Swift:将html字符串转换为属性字符串时添加空格
- python - 请帮助我使用 python 将 ['1,7'] 转换为 [1,7]
- javascript - 显示不正确?
- javascript - 在网站和移动应用程序之间整合数据