Swagger上傳檔案及寄信加附檔(筆記)

Swagger

1.上傳檔案

2.寄信加附檔

enctype這個屬性管理的是表單的MIME編碼

①application/x-www-form-urlencoded (默認值):

在AJAX里不寫有可能會報錯,

但是在HTML的form表單里是可以不寫 enctype="application/x-www-form-urlencoded"的,

因為默認HTML表單就是這種傳輸編碼類型。

②multipart/form-data:

是用來指定傳輸數據的特殊類型的,

主要就是我們上傳的非文本的內容,

比如圖片或者mp3等等。

③text/plain:

是純文本傳輸的意思,在發送郵件時要設置這種編碼類型,否則會出現接收時編碼混亂的問題,

網路上經常拿text/plain和 text/html做比較,

前者用來傳輸純文本文件,

後者則是傳遞html代碼的編碼類型,

在發送文件時才用得上。


原文網址:https://read01.com/oLgjLj.html
 

ASP.NET WebAPI

在Swagger中若需上傳檔案則須將所有body中的參數類型改為formData

在ASP.NET WebAPI中的Swagger ParameterType更改為formdata須自己加入其屬性(因為沒有[FromForm]此屬性)

第一步:增添其屬性

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SwaggerParameterAttribute : Attribute
{
}

第二步:增加Filter

/// <summary>
/// Class SwaggerParameterOperationFilter.
/// </summary>
/// <seealso cref="Swashbuckle.Swagger.IOperationFilter" />
public class SwaggerParameterOperationFilter : Swashbuckle.Swagger.IOperationFilter
{
	/// <summary>
	/// Applies the specified operation.
	/// </summary>
	/// <param name="operation">The operation.</param>
	/// <param name="schemaRegistry">The schema registry.</param>
	/// <param name="apiDescription">The API description.</param>
	public void Apply(Swashbuckle.Swagger.Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
	{

		//確認是否有加入此Attribute 如果有的話就做
		var requestAttributes = apiDescription.GetControllerAndActionAttributes<SwaggerParameterAttribute>();
		if (requestAttributes.Any())
		{
			operation.parameters = operation.parameters ?? new List<Parameter>();
			//取得Action的參數
			var getActionParameters = apiDescription.ActionDescriptor.GetParameters();
			foreach (var item in getActionParameters)
			{
				//如果底層型別為Object
				if (item.ParameterType.BaseType.Name == typeof(object).Name)
				{
					//檢查是否有此Object 有才做 , 如果是string 在CheckObjectName這邊正常會判定為False , string底層型別為Object,item.ParameterType.Name = String
					var checkObjectName = schemaRegistry.Definitions.ContainsKey(item.ParameterType.Name);
					if (checkObjectName)
					{
						//取得Object裡面的屬性
						var data = schemaRegistry.Definitions[item.ParameterType.Name];
						foreach (var item2 in data.properties)
						{
							//加進Swagger裡面
							operation.parameters.Add(new Parameter
							{
								name = item2.Key,
								description = item2.Value.description,
								@in = "formData",
								required = false,
								type = item2.Value.type,
								@enum = item2.Value.@enum
							});
						}
						//移除Swagger內容

						schemaRegistry.Definitions.Remove(item.ParameterType.Name);
						operation.parameters.Remove(operation.parameters.FirstOrDefault(x => x.@in == "body"));
						var parameterList = new List<Parameter>(operation.parameters.ToList());
						foreach (var parameter in operation.parameters.Where(x => x.@in == "query"))
						{

							parameterList.Remove(parameter);
						}

						operation.parameters = parameterList;
					}
				}
			}  
		}
	}
}

第三步:在Controller的Method中加入其屬性[SwaggerParameter]

[HttpPost]
[SwaggerParameter]
[Route("uploadFilesAndSendEmail")]
public async Task<IHttpActionResult> UploadFileAndSendEmail([FromUri]ModelClass model)
{
	var subject = HttpContext.Current.Request.Form["subject"];
	//若為htmlcode則需Encode
	var content = HttpUtility.HtmlEncode(HttpContext.Current.Request.Form["Content"]);
	var guid = Guid.NewGuid();
	model.ID = guid;
	model.Subject = subject;
	model.Content = content;
	if (!Request.Content.IsMimeMultipartContent())
	{
		throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
	}

	string root = System.Web.HttpContext.Current.Server.MapPath("~/App_Data/uploads");
	model.Root = root;

	// 若資料夾不存在,則創建該資料夾
	if (!Directory.Exists(root))
	{
		// 創建資料夾  
		Directory.CreateDirectory(root);
	}

	var i = 1;
	var fileNames = new List<string>();

	// 驗證檔案大小及副檔名
	try
	{
		var multipartMemoryStreamProvider = await Request.Content.ReadAsMultipartAsync();
		foreach (var httpcontent in multipartMemoryStreamProvider.Contents)
		{
			using (httpcontent)
			{
				if (httpcontent.Headers.ContentDisposition.FileName != null)
				{
					var fileName = httpcontent.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
					List<string> validExtensions = new List<string> { ".jpg", ".jpeg", ".png" };
					using (var stream = await httpcontent.ReadAsStreamAsync())
					{
						//驗證附檔名
						var extension = Path.GetExtension(fileName.Replace("\"", string.Empty));
						if (!validExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
						{
							if (fileNames.Count() > 0)
							{
								foreach (var file in fileNames)
								{
									File.Delete(Path.Combine(root, file));
								}
							}

							stream.Dispose();
							throw new CustomException(StatusType.FileTypeIsNotSupported);
						}
						else if (stream.Length > 2097152)// 2MB = 2*1024*1024
						{
							
							if (fileNames.Count() > 0)
							{
								foreach (var file in fileNames)
								{
									File.Delete(Path.Combine(root, file));
								}
							}

							stream.Dispose();
							throw new CustomException(StatusType.UploadFileLengthOver);
						}

						// 將檔案名稱抓取出來
						if (fileName.StartsWith("\"") && fileName.EndsWith("\""))
						{
							fileName = fileName.Trim('"');
						}

						if (fileName.Contains(@"/") || fileName.Contains(@"\"))
						{
							fileName = Path.GetFileName(fileName);
						}

						var renameFile = $"{guid}_{i}{extension}";
						fileNames.Add(renameFile);
						// 上傳檔案至Server
						using (var fileStream = new FileStream(Path.Combine(root, renameFile), FileMode.Create))
						{
							await stream.CopyToAsync(fileStream);
						}

						i++;
					}
				}
			}
		}

		model.Attachments = fileNames;
		model.Attachment = string.Join(",", fileNames);
		//寄信
		var result = this._customerService.SendMail("zh-cn", model);
		return this.Ok(result);
	}
	catch (CustomException e)
	{
		throw new CustomException(e.StatusType);
	}
	catch (Exception e)
	{
		throw new Exception(e.Message);
	}
}

SendMail

public bool SendMail(string langID, ReuquestCustomServiceModel model)
{
	var result = default(bool);
	var subject = $"{model.Subject}";
	content += HttpUtility.HtmlDecode(model.Content);
	//// 寄信
	var mailMessage = new MailMessage();
	//// 信件主旨
	mailMessage.Subject = subject;
	//// 信件內容
	mailMessage.Body = HttpUtility.HtmlDecode(content);
	//// 信件內容 是否採用Html格式
	mailMessage.IsBodyHtml = true;
	//// 信件標題編碼
	mailMessage.SubjectEncoding = System.Text.Encoding.UTF8;
	//// 寄件人
	mailMessage.From = new MailAddress(member.Email);
	//// 收件人
	var serviceMail = new List<string>(){"收件人Email"};
	var mailTos = serviceEmail.Value.Split(';');
	foreach (var mailTo in mailTos)
	{
		mailMessage.To.Add(mailTo);
	}

	//加入附檔
	if (model.Attachments.Count() > 0)
	{
		foreach (string fileName in model.Attachments)
		{
			Attachment attfile = new Attachment($"{model.Root}\\{fileName}");
			mailMessage.Attachments.Add(attfile);
		}
	}

	//寄送mail
	this._smtpHelper.SendMail(mailMessage);

	//釋放每個附件,才不會Lock住
	if (mailMessage.Attachments != null && mailMessage.Attachments.Count > 0)
	{
		for (int i = 0; i < mailMessage.Attachments.Count; i++)
		{
			mailMessage.Attachments[i].Dispose();
		}
	}

	return true;
}