如何解决保存表单数据后文件文档附件丢失
我有一个包含文档上传功能的简单表单。当我提交数据时,文档上传数据保存成功,但有时上传的文件没有保存在服务器路径上,并且数据库中的文档列正在更新NULL。此问题并非每次都发生,但在极少数情况下发生。我已经检查了日志文件,但没有发现任何异常,也没有出现异常,提交数据后它只是说数据提交成功但上传的文档丢失。
'home-component.ts'
Submit() {
if (this.requestForm.invalid || !this.IsDocumentUploaded) {
for (const key of Object.keys(this.requestForm.controls)) {
if (this.requestForm.controls[key].invalid) {
const invalidControl = this.el.nativeElement.querySelector('[formcontrolname="' + key + '"]');
invalidControl.focus();
break;
}
}
return;
}
this.ShowPageOneDiv = false;
this.ShowSpinner = true;
this.apiService.Submit(this.requestForm.value).subscribe(
res => {
const recaptcha = res;
const filesToUpload = [];
filesToUpload.push(this.DocumentFile);
if (this.IsCoverLetterUploaded) {
filesToUpload.push(this.CoverLetterFile);
}
this.apiService.UploadFile(recaptcha,filesToUpload).subscribe(
() => {
'Send notification to user'
this.apiService.Notify(recaptcha).subscribe(
docId => {
this.RegistryNumber = docId;
this.ShowConfirmationMessage = true;
this.ShowSpinner = false;
},err => {
this.ShowErrorMessage = true;
this.ShowSpinner = false;
console.log(err);
}
)
},() => {
console.log("Send notification to user anyway,but indicate that file upload Failed");
this.apiService.Notify(recaptcha).subscribe(
registryNumber => {
this.RegistryNumber = registryNumber;
this.ShowFailedUploadMessage = true;
this.ShowSpinner = false;
},err => {
this.ShowErrorMessage = true;
this.ShowSpinner = false;
console.log(err);
}
)
}
)
},error => {
this.ShowErrorMessage = true;
this.ShowSpinner = false;
console.log(error);
});
}
'app-service.ts'
import { Injectable } from '@angular/core';
import { HttpClient,HttpHeaders } from '@angular/common/http';
import { ProductionUpload } from './ProductionUpload';
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private _http: HttpClient) { }
Submit(productionUpload: ProductionUpload) {
const apiUrl = window.location.href + 'ProductionUpload/Add';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',}),responseType: 'text' as 'json'
};
productionUpload.ReplacementFiles = +productionUpload.ReplacementFiles;
productionUpload.IsDeleted = false;
productionUpload.IsProcessed = false;
return this._http.post<string>(apiUrl,productionUpload,httpOptions);
}
UploadFile(recaptcha,filetoUpload: File[]) {
const apiUrl = window.location.href + 'ProductionUpload/Upload';
const formData: FormData = new FormData();
console.log("add the files");
if (filetoUpload && filetoUpload.length) {
filetoUpload.forEach(file => formData.append('files',file));
}
formData.append('data',recaptcha)
return this._http.post(apiUrl,formData);
}
Notify(recaptcha) {
const apiUrl = window.location.href + 'ProductionUpload/Notify/';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',responseType: 'text' as 'json'
};
return this._http.post<string>(apiUrl,JSON.stringify(recaptcha),httpOptions);
}
}
'MyControllers.cs'
[HttpPost]
[Route("Add")]
public string AddRecord([FromBody]ProductionUpload data)
{
string recaptcha = string.Empty;
try
{
console.log("Validate the model");
if (!ModelState.IsValid)
{
throw new Exception("Server-side validation message(s): " +
ModelState.Values.Select(v => v.Errors.Select(e => e.ErrorMessage).Aggregate((a,b) => a + "; " + b))
.Aggregate((a,b) => a + "; " + b));
}
console.log("Validate Recaptcha response");
if (!ValidateRecaptchaResponse(data.Recaptcha))
{
throw new Exception("Invalid Recaptcha response: " + data.Recaptcha);
}
console.log("Save the request to DB");
data.DateOfSubmission = DateTime.UtcNow;
_context.ProductionUploads.Add(data);
_context.SaveChanges();
data.RegistryNumber = "P" + data.Id.ToString().PadLeft(6,'0');
_context.SaveChanges();
recaptcha = data.Recaptcha;
}
catch (Exception ex)
{
SendExceptionEmail(ex);
_logger.LogError("{0}\n{1}",ex.Message,ex.StackTrace);
throw;
}
return recaptcha;
}
[HttpPost]
[disableRequestSizeLimit]
[Route("Upload")]
public void UploadDocument()
{
List<ProductionUpload> fileData = new List<ProductionUpload>();
try
{
var recaptcha = Request.Form["data"].ToString();
var files = Request.Form.Files;
console.log("Validate the document");
if (files.Count > 0)
{
uint maximumDocumentSize = _configuration.GetSection("AppSettings").GetValue<uint>("MaximumDocumentSize");
List<FileType> allowedDocumentTypes = _configuration.GetSection("AppSettings:AllowedDocumentTypes").Get<List<FileType>>();
var fileExt = Path.GetExtension(files[0].FileName);
if (files[0].Length == 0 || files[0].Length > maximumDocumentSize ||
(!allowedDocumentTypes.Any(ft => ft.Extension.ToLower() == fileExt.ToLower() && (string.IsNullOrEmpty(ft.ContentType) || ft.ContentType.ToLower() == files[0].ContentType.ToLower()))))
{
throw new Exception(string.Format("Server-side file validation failure: {0},{1} bytes,{2} content type",files[0].FileName,files[0].Length,files[0].ContentType));
}
}
console.log("Validate the cover letter");
if (files.Count > 1)
{
uint maximumCoverLetterSize = _configuration.GetSection("AppSettings").GetValue<uint>("MaximumCoverLetterSize");
List<FileType> allowedCoverLetterTypes = _configuration.GetSection("AppSettings:AllowedCoverLetterTypes").Get<List<FileType>>();
var fileExt = Path.GetExtension(files[1].FileName);
if (files[1].Length == 0 || files[1].Length > maximumCoverLetterSize ||
(!allowedCoverLetterTypes.Any(ft => ft.Extension.ToLower() == fileExt.ToLower() && (string.IsNullOrEmpty(ft.ContentType) || ft.ContentType.ToLower() == files[1].ContentType.ToLower()))))
{
throw new Exception(string.Format("Server-side file validation failure: {0},files[1].FileName,files[1].Length,files[1].ContentType));
}
}
console.log("Get the prevIoUsly saved Submission from the database");
ProductionUpload productionUpload = _context.ProductionUploads.SingleOrDefault(sr => sr.Recaptcha == recaptcha);
if (productionUpload == null || productionUpload.Id == 0)
{
throw new Exception("Invalid Recaptcha response: " + recaptcha);
}
console.log("Save the uploaded files");
string fileUploadpath = _configuration.GetSection("AppSettings").GetValue<string>("FileUploadpath");
string pathToSave = Path.Combine(fileUploadpath,Guid.NewGuid().ToString());
if (!Directory.Exists(pathToSave))
Directory.CreateDirectory(pathToSave);
for (int i = 0; i < files.Count; i++)
{
var fileName = Path.GetFileName(files[i].FileName);
var localFileName = ReplaceInvalidCharacters(fileName);
var dbPath = Path.Combine(pathToSave,localFileName);
using (var stream = new FileStream(dbPath,FileMode.Create))
{
files[i].copyTo(stream);
}
if (i == 0)
{
productionUpload.Documents = dbPath;
}
else
{
productionUpload.CoverLetter = dbPath;
}
}
_context.SaveChanges();
}
catch (Exception ex)
{
SendExceptionEmail(ex);
_logger.LogError("{0}\n{1}",ex.StackTrace);
throw;
}
}
[HttpPost]
[Route("Notify")]
public string Notify([FromBody]string recaptcha)
{
string registryNumber = string.Empty;
try
{
console.log("Get the prevIoUsly saved Submission from the database");
ProductionUpload productionUpload = _context.ProductionUploads.SingleOrDefault(sr => sr.Recaptcha == recaptcha);
if (productionUpload == null || productionUpload.Id == 0)
{
throw new Exception("Invalid Recaptcha response: " + recaptcha);
}
console.log("Generate a PDF version of the submission form");
string templateHtml = GetPdfHtml(productionUpload);
string pdfFilePath = GeneratePdfFile(templateHtml,productionUpload.RegistryNumber);
SendEmail(productionUpload.ContactName,productionUpload.Email,productionUpload.RegistryNumber,pdfFilePath);
registryNumber = productionUpload.RegistryNumber;
}
catch (Exception ex)
{
SendExceptionEmail(ex);
_logger.LogError("{0}\n{1}",ex.StackTrace);
throw;
}
return registryNumber;
}
public static string ReplaceInvalidCharacters(string fileName)
{
string replacementCharacter = "_";
Regex pattern = new Regex("[;:*?\"<>|&',+@!$=%~()]");
string newFileName = pattern.Replace(fileName,replacementCharacter);
return newFileName;
}
private string GetPdfHtml(ProductionUpload data)
{
string templateHtml = System.IO.File.ReadAllText(
Path.Combine(_environment.ContentRootPath,_configuration.GetSection("AppSettings").GetValue<string>("PDFTemplate")));
TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
DateTime dateOfSubmission = TimeZoneInfo.ConvertTimeFromUtc(data.DateOfSubmission,timeZoneInfo);
templateHtml = templateHtml.Replace(DateTimePDF,dateOfSubmission.ToString("dd/MM/yyyy hh:mm:ss tt"));
templateHtml = templateHtml.Replace(Id,data.RegistryNumber.ToString());
templateHtml = templateHtml.Replace(ProducingEntity,data.ProducingEntity);
templateHtml = templateHtml.Replace(PartyCode,data.PartyCode);
templateHtml = templateHtml.Replace(RepresentedBy,data.RepresentedBy);
templateHtml = templateHtml.Replace(ContactName,data.ContactName);
templateHtml = templateHtml.Replace(Email,data.Email);
templateHtml = templateHtml.Replace(ContactNumber,data.ContactNumber);
templateHtml = templateHtml.Replace(ReferenceNumber,data.ReferenceNumber);
templateHtml = templateHtml.Replace(NoticetoProduceNumber,data.NoticetoProduceNumber);
templateHtml = templateHtml.Replace(ReplacementFiles,data.ReplacementFiles == 1 ? "Yes" : data.ReplacementFiles == 0 ? "No" : string.Empty);
templateHtml = templateHtml.Replace(UploadMaterial,data.UploadMaterial);
templateHtml = templateHtml.Replace(TrancheNumber,data.TrancheNumber);
templateHtml = templateHtml.Replace(Password,data.Password);
templateHtml = templateHtml.Replace(Description,string.IsNullOrEmpty(data.Description) ? string.Empty : data.Description.Replace("\n","<br />"));
templateHtml = templateHtml.Replace(CoverLetter,string.IsNullOrEmpty(data.CoverLetter) ? string.Empty : Path.GetFileName(data.CoverLetter));
templateHtml = templateHtml.Replace(Documents,Path.GetFileName(data.Documents));
return templateHtml;
}
private string GeneratePdfFile(string html,string docId)
{
string filePath = null;
console.log("create the HTML to PDF converter");
HtmlToPdf htmlToPdfConverter = new HtmlToPdf();
htmlToPdfConverter.SerialNumber = _configuration.GetSection("AppSettings").GetValue<string>("HTMLtoPDFKey");
console.log("Setting marins");
htmlToPdfConverter.Document.Margins = new PdfMargins(0,60,0);
htmlToPdfConverter.Document.Footer.Enabled = true;
htmlToPdfConverter.Document.Footer.Height = 60;
float pdfpageWidth = htmlToPdfConverter.Document.PageOrientation == pdfpageOrientation.Portrait ? htmlToPdfConverter.Document.PageSize.Width : htmlToPdfConverter.Document.PageSize.Height;
float footerHeight = htmlToPdfConverter.Document.Footer.Height;
PdfHtmlWithPlaceHolders htmlWithPageNumbers = new PdfHtmlWithPlaceHolders(-30,footerHeight - 50,"<div style=\"float:right;\"><span style =\"font-size: 11pt; color: black;font-family:Calibri;\">Page {CrtPage} of {PageCount}</span></div>",null);
htmlToPdfConverter.Document.Footer.Layout(htmlWithPageNumbers);
htmlToPdfConverter.PageCreatingEvent += new pdfpageCreatingDelegate(htmlToPdfConverter_PageCreatingEvent);
try
{
console.log("convert HTML to PDF");
byte[] pdfBuffer = htmlToPdfConverter.ConvertHtmlToMemory(html,null);
string path1 = Path.Combine(_configuration.GetSection("AppSettings").GetValue<string>("SubmissionDataPath"));
if (!Directory.Exists(path1))
Directory.CreateDirectory(path1);
filePath = Path.Combine(path1,docId + ".pdf");
System.IO.File.WriteallBytes(filePath,pdfBuffer);
}
finally
{
htmlToPdfConverter.PageCreatingEvent -= new pdfpageCreatingDelegate(htmlToPdfConverter_PageCreatingEvent);
}
return filePath;
}
private void htmlToPdfConverter_PageCreatingEvent(pdfpageCreatingParams eventParams)
{
pdfpage pdfpage = eventParams.pdfpage;
pdfpage.displayFooter = true;
}
'appsettings.json'
"AllowedFileTypes": [
{
"ContentType": "application/pdf","Extension": ".pdf"
},{
"ContentType": "","Extension": ".rtf"
},"Extension": ".txt"
},{
"ContentType": "application/msword","Extension": ".doc"
},{
"ContentType": "application/vnd.openxmlformats-officedocument.wordprocessingml.document","Extension": ".docx"
},{
"ContentType": "application/vnd.ms-powerpoint","Extension": ".ppt"
},"Extension": ".pps"
},{
"ContentType": "application/vnd.openxmlformats-officedocument.presentationml.presentation","Extension": ".pptx"
},"Extension": ".ppts"
},{
"ContentType": "application/vnd.ms-excel","Extension": ".xls"
},{
"ContentType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","Extension": ".xlsx"
},{
"ContentType": "application/vnd.oasis.opendocument.text","Extension": ".odt"
},{
"ContentType": "application/vnd.oasis.opendocument.spreadsheet","Extension": ".ods"
},{
"ContentType": "application/vnd.oasis.opendocument.presentation","Extension": ".odp"
},"Extension": ".wpd"
},"Extension": ".qpw"
},"Extension": ".shw"
},{
"ContentType": "application/x-iwork-pages-sffpages","Extension": ".pages"
},{
"ContentType": "application/x-iwork-numbers-sffnumbers","Extension": ".numbers"
},{
"ContentType": "application/x-iwork-keynote-sffkey","Extension": ".key"
},{
"ContentType": "image/jpeg","Extension": ".jpg"
},"Extension": ".jpeg"
},{
"ContentType": "image/tiff","Extension": ".tif"
},"Extension": ".tiff"
},{
"ContentType": "image/png","Extension": ".png"
},"Extension": ".heic"
},"Extension": ".heif"
},"Extension": ".wav"
},"Extension": ".mp3"
},"Extension": ".m4a"
},"Extension": ".oga"
},"Extension": ".ogg"
},"Extension": ".ogv"
},"Extension": ".flac"
},"Extension": ".wma"
},"Extension": ".wmv"
},"Extension": ".mov"
},"Extension": ".avi"
},"Extension": ".mpeg"
},"Extension": ".mpg"
},"Extension": ".mp4"
},"Extension": ".m4v"
},"Extension": ".3gp"
},"Extension": ".3g2"
}
],"MaximumFileSize": "4294967295",
这有时是网络问题导致的吗?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。