Мне было интересно, можно ли отправить файл (который мне нужен только ".pdf", ".jpg" или ".png") вместе с сырым JSON. Все мои конечные точки до сих пор отправляют raw JSON (который я тестирую через Postman, поскольку интерфейс еще не существует), предполагается, что отправка данных формы будет отправляться с использованием Angular Js. Я еще не знаю Angular Js, поэтому я не могу представить, как это будет работать.
Подпись конечной точки выглядит следующим образом:
[Route("Post")]
[CustomAuthorize(Roles = "User, Admin")]
[ValidateJWT]
public async Task<IHttpActionResult> Post(HttpRequestMessage request, SalesOrderViewModel orderData)
Модель представления - это просто класс aС# с множеством свойств строки, которые конвертирует модель из JSON.
Я хотел бы знать, возможна ли отправка сырого JSON и файла, который пользователь будет выбирать, в той же конечной точке с помощью Web API 2. Это?
Заранее спасибо.
Изменить: просто проверено, что вам не нужно использовать IEnumerable<byte>
. Использование byte[]
отлично работает.
WebApi поддерживает десериализацию массива JSON для IEnumerable<T>
, так что вы можете получать байты, объявляя с помощью IEnumerable<byte>
.
В следующем примере показано, как загрузить изображение:
public class ImageModel
{
public string Name { get; set; }
public IEnumerable<byte> Bytes { get; set; }
}
В вашем контроллере. Запись изображения на диск:
private string WriteImage(byte[] arr)
{
var filename = $@"images\{DateTime.Now.Ticks}.";
using (var im = Image.FromStream(new MemoryStream(arr)))
{
ImageFormat frmt;
if (ImageFormat.Png.Equals(im.RawFormat))
{
filename += "png";
frmt = ImageFormat.Png;
}
else
{
filename += "jpg";
frmt = ImageFormat.Jpeg;
}
string path = HttpContext.Current.Server.MapPath("~/") + filename;
im.Save(path, frmt);
}
return $@"http:\\{Request.RequestUri.Host}\{filename}";
}
HttpContext.Current.Server.MapPath("~/")
даст внутренний путь работы сервера. Request.RequestUri.Host
возвращает имя хоста.
public IHttpActionResult UploadImage(ImageModel model)
{
var imgUrl = WriteImage(model.Bytes.ToArray());
// Some code
}
В HTML:
<input type="file" id="imageFile"/>
Метод загрузки для AngularJS:
$scope.upload = function () {
var file = document.getElementById("imageFile").files[0];
var r = new FileReader();
r.onloadend = function (e) {
var arr = Array.from(new Uint8Array(e.target.result));
var uploadData = {
Name: "Name of Image",
Bytes: arr
}
console.log(uploadData);
$http.post('api/Uploader/UploadImage', uploadData)
.then(
function (response) {
console.log(response);
},
function (reason) {
console.log(reason);
})
}
r.readAsArrayBuffer(file);
}
Вы не можете направлять сообщение с помощью asplication/json, но вы можете сделать это с помощью нескольких полей формы (в виде данных формы), файлов + данных, где значение данных может быть JSON.
Я не рекомендую этот метод, но трюк:
public async Task<IHttpActionResult> Post()
{
if (!Request.Content.IsMimeMultipartContent())
{
Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
}
//load in a memory stream or in azure blob storage
var uploadFolder = "~/App_Data/FileUploads"; // to demonstrate the upload so please don't comment about where I'm saving the file, don't recommend this under no circumstance
var root = HttpContext.Current.Server.MapPath(uploadFolder);
Directory.CreateDirectory(root);
var provider = new MultipartFormDataStreamProvider(root);
var result = await Request.Content.ReadAsMultipartAsync(provider);
if (result.FileData.FirstOrDefault() == null)
{
return BadRequest("No import file was attached");
}
var uploadedFileInfo = new FileInfo(result.FileData.First().LocalFileName);
var model = result.FormData["model"];
if (model == null)
{
return BadRequest("Model is missing");
}
var parameters = JsonConvert.DeserializeObject<Coords>(model);
var byteArray = File.ReadAllBytes(uploadedFileInfo.FullName);
//..process the bytes
//..process json passed in headers
}
И модель:
public class Coords
{
public Cord[] cords { get; set; }
}
public class Cord
{
public int x { get; set; }
public object y { get; set; }
}
Почтальон звонит: