Я хочу использовать Angular 8 с Asp.Net Web Api для загрузки файла изображения и сохранения его в таблице базы данных сервера SQL, где столбец изображения определен как varbinary.
Примечание: я могу сделатьэто с помощью веб-формы ASP.Net просто отлично (я включил его ниже). Поэтому я пытаюсь имитировать загрузку веб-формы, но использую Angular в качестве внешнего интерфейса.
Для загрузки файла в Angular 8 я воспользовался этим советом: https://www.tutsmake.com/new-angular-8-upload-file-or-image-tutorial-example/
В Angularкод метода компонента, я получаю ошибку. Он не любит 'formData' в этой строке: this.imageService.addImage (formData) .subscribe
В нем говорится: Аргумент типа 'formData' не может быть назначен параметру типа Image. Свойство 'ImageData' отсутствует в типе FormData.
См. Определение в моем классе моделей Angular.
Моя проблема в том, как получить загруженный файл изображения Angular в формат varbinary для передачи в Asp.Net Web Api? Является ли файл изображения двоичными данными? Если нет, можно ли преобразовать его в двоичный файл в Angular?
Вот весь код. Примечание: не весь код включен для простоты.
Определение таблицы моего сервера 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
Код метода компонента Angular:
// This is from: https://www.tutsmake.com/new-angular-8-upload-file-or-image-tutorial-example/
// but modified to use my Asp.Net web api.
fileData: File = null;
// Is the image file binary data? If not, can it be converted here to binary?
fileProgress(fileInput: any) {
this.fileData = <File>fileInput.target.files[0];
}
onSubmit() {
const formData = new FormData();
formData.append('file', this.fileData);
// Call the service to add the image.
this.imageService.addImage(formData).subscribe(
() => {
this.message = 'Image Loaded Successfully';
})
}
Метод обслуживания изображений My Angular:
// 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" })
};
return this.http.post<Image>(this.url + "/AddImage/", image, httpOptions);
}
Класс модели My Angular:
export class Image {
ImageData: Binary[];
}
Модель данных My Asp.Net Web Api:
namespace PrototypeWebApi2.Models
{
public class Image
{
public byte[] ImageData { get; set; } <--- Note: I'm not sure if this is the correct type.
}
}
Метод My Asp.Net Web Api:
[HttpPost]
[Route("AddImage")]
public IHttpActionResult PostImage(Image data)
{
try
{
return Ok(dataaccesslayer.AddImage(data));
}
catch (Exception)
{
throw;
}
}
Метод уровня доступа к данным My 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, который загружает файл изображения и работает нормально:
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 (MediaUploadFile.HasFile)
{
String[] allowedExtensions = { ".gif", ".png", ".jpeg", ".jpg", ".bmp" };
for (int i = 0; i < allowedExtensions.Length; i++)
{
if (fileExtension == allowedExtensions[i])
{
fileOK = true;
}
}
}
else
{
LabelAddStatus.Visible = true;
LabelAddStatus.ForeColor = System.Drawing.Color.Red;
LabelAddStatus.Text = "No image file was selected for upload.";
}
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
{
dbFunc.OpenDB();
SqlCommand cmd = new SqlCommand("dbo.InsertImages", dbFunc.objConn);
cmd.Parameters.Clear();
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@ImageData", SqlDbType.VarBinary).Value = bytes;
cmd.ExecuteNonQuery();
string pageUrl = Request.Url.AbsoluteUri.Substring(0, Request.Url.AbsoluteUri.Count()- Request.Url.Query.Count());
Response.Redirect(pageUrl + "?MediaAction=add");
}
catch (Exception ex)
{
strErrorMessage = "Insert error in AddMediaButton_Click(), on call to InsertImages procedure. Error: " + ex.Message + " Source: " + ex.Source;
// Set the UI.
LabelAddStatus.Visible = true;
LabelAddStatus.ForeColor = System.Drawing.Color.Red;
LabelAddStatus.Text = "Unable to insert the new image file to the database. " + strErrorMessage;
}
finally
{
dbFunc.CloseDB();
}
}
else
{
LabelAddStatus.Visible = true;
LabelAddStatus.ForeColor = System.Drawing.Color.Red;
LabelAddStatus.Text = "Unable to accept the file type. Only these (.gif, .png, .jpeg, .jpg, .bmp, .mpeg, .mpg and .mp4) can be uploaded";
}
}