angular - 尝试/如何将图像文件从 Angular 前端发布到 .NET CORE 后端 API --
问题描述
我想知道最好的方法是什么。
从我的 Angular 8 应用程序中,我选择了一个 img 文件,并希望将此图像文件发送到 .NET Core API 后端。后端服务应将此 img 保存在数据库中。
我的图像选择器的 html -
<div class="image-picker" (click)="fileInput.click()">
<mat-icon [class.small]="imageUrl">file_upload</mat-icon>
<canvas width="500" height="380" #canvas hidden="true"></canvas>
<input #fileInput type="file" hidden="true" (change)="imageDataChanged($event)">
</div>
各自的 .ts 代码 -
imageDataChanged($event) {
var file = $event.target.files[0];
console.log(file);
var reader = new FileReader();
// get data from file input and emit as dataUrl
reader.addEventListener("load", () => {
var ctx = this.canvas.nativeElement.getContext('2d');
this.imageUrl = reader.result;
this.imagePicked.emit(this.imageUrl);
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
所以我进入我的控制台,与我选择的文件相关的详细信息。像名称、大小、日期、修改日期......单击提交按钮后,我想将此文件发布到后端 API。我的问题是 - 以什么格式以及如何。base64 图像?那是什么代码。我该怎么做。就像我说的,我的后端在 .NET Core 中。
这是我尝试的代码 -
[HttpPost]
[Route("CaptureSaveImg")]
public IActionResult CaptureSaveImg(HttpContext context)
{
string imageName = null;
var httpRequest = context.Request;
var postedFile = httpRequest.Form.Files["Image"];
try
{
if(postedFile!=null)
{
var fileName = postedFile.FileName;
var myUniqueFileName = Convert.ToString(Guid.NewGuid());
var fileExtension = Path.GetExtension(fileName);
var newFileName = string.Concat(myUniqueFileName, fileExtension);
var filepath = Path.Combine(_environment.WebRootPath, "CameraPics") + $@"\{newFileName}";
if (!string.IsNullOrEmpty(filepath))
{
// Storing Image in Folder
StoreInFolder(postedFile, filepath);
}
var imageBytes = System.IO.File.ReadAllBytes(filepath);
if (imageBytes != null)
{
StoreInDatabase(imageBytes);
}
return Json(new { Success = true, Message = "Image Saved." });
}
else
{
return Json(new { Success = false, Message = "An error occurred while saving the image." });
}
}
catch(Exception exp)
{
return Json(new { Success =false, Message="An unexpected error occurred!"});
}
}
private void StoreInDatabase(byte[] imageBytes)
{
try
{
if (imageBytes != null)
{
string base64String = Convert.ToBase64String(imageBytes, 0, imageBytes.Length);
string imageUrl = string.Concat("data:image/jpg;base64,", base64String);
ImageStore imageStore = new ImageStore()
{
CreateDate = DateTime.Now,
ImageBase64String = imageUrl,
ImageId = 0
};
_context.ImageStores.Add(imageStore);
_context.SaveChanges();
}
}
catch (Exception exp)
{
throw exp.InnerException;
}
}
private void StoreInFolder(IFormFile file, string fileName)
{
try
{
using (FileStream fs = System.IO.File.Create(fileName))
{
file.CopyTo(fs);
fs.Flush();
}
}
catch (Exception exp)
{
throw exp.InnerException;
}
}
用于按钮单击的 html -
<button class="btn btn-primary btn-lg btn-block" type="button" (click)="OnSubmit(Image)" >UPLOAD</button>
.ts 按钮点击 -
OnSubmit(file: File)
{
this.userRestService.uploadImage(this.fileToUpload)
.subscribe((data: any) => {
console.log('Done successfully! '+data.Message);
this.imageUrl = null;
});
}
在使用-休息服务中 -
fileToUpload: File = null;
uploadImage(file: File) {
var reqHeader = new HttpHeaders({ 'No-Auth': 'True' });
const formData: FormData = new FormData();
formData.append('Image', file, file.name);
return this.http.post(this.baseUrl +'CaptureSaveImg', formData, { headers: reqHeader });
}
我想先将它保存在本地文件夹路径中,然后从那里读取文件并保存在数据库中。我知道当我尝试将其发布为 fileToUpload 时,它可能正在发送 null。
我面临的问题 - 我从前端发布/发送什么到 API。如何。你能告诉我一些可以实现这一点的代码吗?你能给我一个分步指南来实现这一目标吗?
随时询问有关我尝试的更多详细信息,以获得更好的洞察力。谢谢
更新:
我之前忘了提到我的图像选择器组件基本上是一个单独的角度组件,我在主页中使用它。所以 imageDataChanged($event) 代码也在那个组件中。让我发帖。
<input #fileInput type="file" hidden="true" (change)="imageDataChanged($event)">
.ts 代码 -
imageDataChanged($event) {
var file = $event.target.files[0];
this.ds.selectedFile = file;
if (file.length===0) {
return;
}
var reader = new FileReader();
// get data from file input and emit as dataUrl
reader.addEventListener("load", () => {
var ctx = this.canvas.nativeElement.getContext('2d');
this.imageUrl = reader.result;
this.imagePicked.emit(this.imageUrl);
}, false);
if (file) {
reader.readAsDataURL(file);
}
const formData = new FormData();
formData.append(file.name, file);
this.ds.formDataPost = formData;
}
这里的 ds 只不过是一个中间数据共享可注入类。
@Injectable()
export class DataSharingService {
public selectedFile: any;
public formDataPost: any;
}
现在,我的 OnSubmit 代码 -
OnSubmit()
{
console.log(this.ds.formDataPost);
const uplRequest = new HttpRequest('POST', this.baseUrl + '/CaptureSaveImg', this.ds.formDataPost, { reportProgress: true });
this.http.request(uplRequest)
.subscribe((data: any) =>
{
if (data.Success == "true")
{
console.log("Upload successful.");
}
else
{
console.log("Problem while uploading file.");
}
})
}
我刚刚收到错误 - core.js:6014 错误类型错误:您在预期流的位置提供了“未定义”。您可以提供 Observable、Promise、Array 或 Iterable。
我想我很接近。需要任何转换吗?还是数据格式?
解决方案
我通过以 Base 64 格式保存到数据库来完成此操作。这很方便,因为在将客户端上的图像立即转换为字符串后,发布到服务器并保存到数据库是微不足道的。
myForm = new FormGroup({
foo: new FormControl(''), // etc...
imageBase64: new FormControl('')
});
constructor(private cd: ChangeDetectorRef) { }
onImageAttached(event): void {
const reader = new FileReader();
if (event.target.files && event.target.files.length) {
const [file] = event.target.files;
reader.readAsDataURL(file);
reader.onload = () => {
this.myForm.patchValue({
imageBase64: reader.result
});
// need to run CD since file load runs outside of zone
this.cd.markForCheck();
};
}
}
稍后,如果您在应用程序中显示这些图像,您可以将该 base64 字符串一直发送到 DOM。
另一方面,如果你有一个 web 服务器来渲染你的 Angular 客户端,你也可以出于性能原因在服务器上转换为一个文件。这为您的图像提供了一条应用路径。
public class AppImageController : Controller
{
[HttpGet]
public async Task<IActionResult> Index(int id)
{
var imageBase64 = await _imageRepository.GetByIdAsync(id);
var mimeStartIndex = imageBase64.IndexOf("image/");
var mime = imageBase64
.Substring(
mimeStartIndex,
result.Data.Attachment.IndexOf(';') - mimeStartIndex
);
var content = imageBase64
.Remove(0, result.Data.Attachment.LastIndexOf(',') + 1);
var bytes = Convert.FromBase64String(content);
return File(bytes, mime.Length > 0 ? mime : "image/png");
}
}
<img src="AppImage/Index/{{appImage.id}}"
alt="{{appImage.name}}">
这并不是说将图像保存到数据库始终是最好的选择。保存到服务器文件系统、AWS S3 文件存储等都是非常可行的选择。您可以研究这些方法之间的权衡取舍。
推荐阅读
- excel - 将带有单元格锚定图像的电子表格导入 SQLite 数据库
- apache-zookeeper - 如何实现自定义执行器端点来检查动物园管理员的健康状况?
- batch-file - 批处理文件:以缩进顺序列出目录中的所有文件
- node.js - 在 Angular 8 应用程序中调用 nodejs kafka 脚本
- php - 使用 CURL 接收数据,然后将数据发送到外部 webhook
- octobercms - 为什么十月 CMS Markdown 编辑器会以这种奇怪的格式添加图像?![](http://)
- c++ - 如何从存储在 QByteArray 中的十六进制值计算校验和
- sql - 加入可空列
- spring - 用于连接到 Postgres 的 Spring 配置。需要bean:'org.flywaydb.core.internal.jdbc.JdbcTemplate'
- node.js - process.hrtime 返回不匹配的秒和毫秒