Currently building a web api for the existing web-based media services to encode uploaded videos.
The goal of my solution is to create a api call where i'll be sending the mp4 link and do the processing (encoding and streaming of the given mp4 link). I was able to fetch the mp4 and download to the server and reupload to its own blob storage. However if I check the AMS explorer, every parameters I passed exists except for the filesize. Here's my WEB API call I created (a total replicate of the existing media service form method. (https://tiltestingstreaming.azurewebsites.net/
)
[HttpPost]
public JsonResult UploadApi(String video_url)
{
var id = 1;
WebClient client = new WebClient();
var videoStream = new MemoryStream(client.DownloadData(video_url));
var container = CloudStorageAccount.Parse(mediaServiceStorageConnectionString).CreateCloudBlobClient().GetContainerReference(mediaServiceStorageContainerReference);
container.CreateIfNotExists();
var fileName = Path.GetFileName(video_url);
var fileToUpload = new CloudFile()
{
BlockCount = 1,
FileName = fileName,
Size = videoStream.Length,
BlockBlob = container.GetBlockBlobReference(fileName),
StartTime = DateTime.Now,
IsUploadCompleted = false,
UploadStatusMessage = string.Empty
};
Session.Add("CurrentFile", fileToUpload);
byte[] chunk = new byte[videoStream.Length];
//request.InputStream.Read(chunk, 0, Convert.ToInt32(request.Length));
//JsonResult returnData = null;
string fileSession = "CurrentFile";
CloudFile model = (CloudFile)Session[fileSession];
var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(
string.Format(CultureInfo.InvariantCulture, "{0:D4}", id)));
try
{
model.BlockBlob.PutBlock(
blockId,
videoStream, null, null,
new BlobRequestOptions()
{
RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(10), 3)
},
null);
}
catch (StorageException e)
{
model.IsUploadCompleted = true;
model.UploadStatusMessage = "Failed to Upload file. Exception - " + e.Message;
return Json(new { error = true, isLastBlock = false, message = model.UploadStatusMessage });
}
var blockList = Enumerable.Range(1, (int)model.BlockCount).ToList<int>().ConvertAll(rangeElement => Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0:D4}", rangeElement))));
model.BlockBlob.PutBlockList(blockList);
var duration = DateTime.Now - model.StartTime;
float fileSizeInKb = model.Size / 1024;
string fileSizeMessage = fileSizeInKb > 1024 ? string.Concat((fileSizeInKb / 1024).ToString(CultureInfo.CurrentCulture), " MB") : string.Concat(fileSizeInKb.ToString(CultureInfo.CurrentCulture), " KB");
model.UploadStatusMessage = string.Format(CultureInfo.CurrentCulture, "File of size {0} took {1} seconds to upload.", fileSizeMessage, duration.TotalSeconds);
IAsset mediaServiceAsset = CreateMediaAsset(model);
model.AssetId = mediaServiceAsset.Id;
//if (id == model.BlockCount){CommitAllChunks(model);}
return Json(new { error = false, isLastBlock = false, message = string.Empty, filename = fileName,filesize = videoStream.Length });
}
Functions used on the form-method solution.
[HttpPost]
public ActionResult SetMetadata(int blocksCount, string fileName, long fileSize)
{
var container = CloudStorageAccount.Parse(mediaServiceStorageConnectionString).CreateCloudBlobClient().GetContainerReference(mediaServiceStorageContainerReference);
container.CreateIfNotExists();
var fileToUpload = new CloudFile()
{
BlockCount = blocksCount,
FileName = fileName,
Size = fileSize,
BlockBlob = container.GetBlockBlobReference(fileName),
StartTime = DateTime.Now,
IsUploadCompleted = false,
UploadStatusMessage = string.Empty
};
Session.Add("CurrentFile", fileToUpload);
return Json(true);
}
[HttpPost]
[ValidateInput(false)]
public ActionResult UploadChunk(int id)
{
HttpPostedFileBase request = Request.Files["Slice"];
byte[] chunk = new byte[request.ContentLength];
request.InputStream.Read(chunk, 0, Convert.ToInt32(request.ContentLength));
JsonResult returnData = null;
string fileSession = "CurrentFile";
if (Session[fileSession] != null)
{
CloudFile model = (CloudFile)Session[fileSession];
returnData = UploadCurrentChunk(model, chunk, id);
if (returnData != null)
{
return returnData;
}
if (id == model.BlockCount)
{
return CommitAllChunks(model);
}
}
else
{
returnData = Json(new
{
error = true,
isLastBlock = false,
message = string.Format(CultureInfo.CurrentCulture, "Failed to Upload file.", "Session Timed out")
});
return returnData;
}
return Json(new { error = false, isLastBlock = false, message = string.Empty });
}
private JsonResult UploadCurrentChunk(CloudFile model, byte[] chunk, int id)
{
using (var chunkStream = new MemoryStream(chunk))
{
var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(
string.Format(CultureInfo.InvariantCulture, "{0:D4}", id)));
try
{
model.BlockBlob.PutBlock(
blockId,
chunkStream, null, null,
new BlobRequestOptions()
{
RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(10), 3)
},
null);
return null;
}
catch (StorageException e)
{
model.IsUploadCompleted = true;
model.UploadStatusMessage = "Failed to Upload file. Exception - " + e.Message;
return Json(new { error = true, isLastBlock = false, message = model.UploadStatusMessage });
}
}
}
private ActionResult CommitAllChunks(CloudFile model)
{
model.IsUploadCompleted = true;
bool errorInOperation = false;
try
{
var blockList = Enumerable.Range(1, (int)model.BlockCount).ToList<int>().ConvertAll(rangeElement => Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0:D4}", rangeElement))));
model.BlockBlob.PutBlockList(blockList);
var duration = DateTime.Now - model.StartTime;
float fileSizeInKb = model.Size / 1024;
string fileSizeMessage = fileSizeInKb > 1024 ? string.Concat((fileSizeInKb / 1024).ToString(CultureInfo.CurrentCulture), " MB") : string.Concat(fileSizeInKb.ToString(CultureInfo.CurrentCulture), " KB");
model.UploadStatusMessage = string.Format(CultureInfo.CurrentCulture, "File of size {0} took {1} seconds to upload.", fileSizeMessage, duration.TotalSeconds);
IAsset mediaServiceAsset = CreateMediaAsset(model);
model.AssetId = mediaServiceAsset.Id;
}
catch (StorageException e)
{
model.UploadStatusMessage = "Failed to upload file. Exception - " + e.Message;
errorInOperation = true;
}
return Json(new
{
error = errorInOperation,
isLastBlock = model.IsUploadCompleted,
message = model.UploadStatusMessage,
assetId = model.AssetId
});
}
private IAsset CreateMediaAsset(CloudFile model)
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(mediaServiceStorageConnectionString);
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer mediaBlobContainer = cloudBlobClient.GetContainerReference(mediaServiceStorageContainerReference);
mediaBlobContainer.CreateIfNotExists();
// Create a new asset.
IAsset asset = context.Assets.Create("UploadedVideo-" + Guid.NewGuid().ToString().ToLower(), AssetCreationOptions.None);
IAccessPolicy writePolicy = context.AccessPolicies.Create("writePolicy", TimeSpan.FromMinutes(120), AccessPermissions.Write);
ILocator destinationLocator = context.Locators.CreateLocator(LocatorType.Sas, asset, writePolicy);
// Get the asset container URI and copy blobs from mediaContainer to assetContainer.
Uri uploadUri = new Uri(destinationLocator.Path);
string assetContainerName = uploadUri.Segments[1];
CloudBlobContainer assetContainer = cloudBlobClient.GetContainerReference(assetContainerName);
string fileName = HttpUtility.UrlDecode(Path.GetFileName(model.BlockBlob.Uri.AbsoluteUri));
var sourceCloudBlob = mediaBlobContainer.GetBlockBlobReference(fileName);
sourceCloudBlob.FetchAttributes();
if (sourceCloudBlob.Properties.Length > 0)
{
IAssetFile assetFile = asset.AssetFiles.Create(fileName);
var destinationBlob = assetContainer.GetBlockBlobReference(fileName);
destinationBlob.DeleteIfExists();
destinationBlob.StartCopy(sourceCloudBlob);
destinationBlob.FetchAttributes();
if (sourceCloudBlob.Properties.Length != destinationBlob.Properties.Length)
model.UploadStatusMessage += "Failed to copy as Media Asset!";
}
destinationLocator.Delete();
writePolicy.Delete();
sourceCloudBlob.Delete(); //delete temp blob
// Refresh the asset.
asset = context.Assets.Where(a => a.Id == asset.Id).FirstOrDefault();
var ismAssetFiles = asset.AssetFiles.FirstOrDefault();
ismAssetFiles.IsPrimary = true;
ismAssetFiles.Update();
model.UploadStatusMessage += " Media file uploaded successfully by id: " + asset.Id;
model.AssetId = asset.Id;
return asset;
}
[HttpPost]
public ActionResult EncodeToAdaptiveBitrateMP4s(string assetId)
{
// Note: You need atleast 1 reserve streaming unit for dynamic packaging of encoded media. If you don't have that, you can't see video file playing.
IAsset inputAsset = GetAssetById(assetId);
string token = string.Empty;
string uploadFileOriginalName = string.Empty;
////// Without preset (say default preset), works very well
//IJob job = context.Jobs.CreateWithSingleTask(MediaProcessorNames.AzureMediaEncoder,
// MediaEncoderTaskPresetStrings.H264AdaptiveBitrateMP4Set720p,
// inputAsset,
// "UploadedVideo-" + Guid.NewGuid().ToString().ToLower() + "-Adaptive-Bitrate-MP4",
// AssetCreationOptions.None);
//job.Submit();
//IAsset encodedOutputAsset = job.OutputMediaAssets[0];
//// XML Preset
IJob job = context.Jobs.Create(inputAsset.Name);
IMediaProcessor processor = GetLatestMediaProcessorByName("Media Encoder Standard");
string configuration = System.IO.File.ReadAllText(HttpContext.Server.MapPath("~/MediaServicesCustomPreset.xml"));
ITask task = job.Tasks.AddNew(inputAsset.Name + "- encoding task", processor, configuration, TaskOptions.None);
task.InputAssets.Add(inputAsset);
task.OutputAssets.AddNew(inputAsset.Name + "-Adaptive-Bitrate-MP4", AssetCreationOptions.None);
job.Submit();
IAsset encodedAsset = job.OutputMediaAssets[0];
// process policy & encryption
ProcessPolicyAndEncryption(encodedAsset);
// Get file name
string fileSession = "CurrentFile";
if (Session[fileSession] != null)
{
CloudFile model = (CloudFile)Session[fileSession];
uploadFileOriginalName = model.FileName;
}
// Generate Streaming URL
string smoothStreamingUri = GetStreamingOriginLocator(encodedAsset, uploadFileOriginalName);
// add jobid and output asset id in database
AzureMediaServicesContext db = new AzureMediaServicesContext();
var video = new Video();
video.RowAssetId = assetId;
video.EncodingJobId = job.Id;
video.EncodedAssetId = encodedAsset.Id;
video.LocatorUri = smoothStreamingUri;
video.IsEncrypted = useAESRestriction;
db.Videos.Add(video);
db.SaveChanges();
if (useAESRestriction)
{
token = AzureMediaAsset.GetTestToken(encodedAsset.Id, encodedAsset);
}
// Remove session
Session.Remove("CurrentFile");
// return success response
return Json(new
{
error = false,
message = "Congratulations! Video is uploaded and pipelined for encoding, check console log for after encoding playback details.",
assetId = assetId,
jobId = job.Id,
locator = smoothStreamingUri,
encrypted = useAESRestriction,
token = token
});
}
The actual challenge that I encounter was, I'm not sure why the filesize of the downloaded remote mp4 file doesn't store in the media services asset file yet I was able to return the value via the json response of the my api call. Please check attached Screenshot of the API response.
Was able to figure out my own problem. All I need to do is to copy the function of my encoding function that was bind to an ActionResult data type. I think ActionResult is part of the form-method solution and I am building a WebAPI call solution of the working form-method.
From the original call function
[HttpPost] public ActionResult EncodeToAdaptiveBitrateMP4s(string assetId)
I copy the entire function into my WebApi Call function, like this:
[HttpPost]
public JsonResult UploadApi(String video_url)
{
var id = 1;
WebClient client = new WebClient();
var videoStream = new MemoryStream(client.DownloadData(video_url));
var container = CloudStorageAccount.Parse(mediaServiceStorageConnectionString).CreateCloudBlobClient().GetContainerReference(mediaServiceStorageContainerReference);
container.CreateIfNotExists();
var fileName = Path.GetFileName(video_url);
var fileToUpload = new CloudFile()
{
BlockCount = 1,
FileName = fileName,
Size = videoStream.Length,
BlockBlob = container.GetBlockBlobReference(fileName),
StartTime = DateTime.Now,
IsUploadCompleted = false,
UploadStatusMessage = string.Empty
};
Session.Add("CurrentFile", fileToUpload);
byte[] chunk = new byte[videoStream.Length];
//request.InputStream.Read(chunk, 0, Convert.ToInt32(request.Length));
//JsonResult returnData = null;
string fileSession = "CurrentFile";
CloudFile model = (CloudFile)Session[fileSession];
var blockId = Convert.ToBase64String(Encoding.UTF8.GetBytes(
string.Format(CultureInfo.InvariantCulture, "{0:D4}", id)));
try
{
model.BlockBlob.PutBlock(
blockId,
videoStream, null, null,
new BlobRequestOptions()
{
RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(10), 3)
},
null);
}
catch (StorageException e)
{
model.IsUploadCompleted = true;
model.UploadStatusMessage = "Failed to Upload file. Exception - " + e.Message;
return Json(new { error = true, isLastBlock = false, message = model.UploadStatusMessage });
}
var blockList = Enumerable.Range(1, (int)model.BlockCount).ToList<int>().ConvertAll(rangeElement => Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0:D4}", rangeElement))));
model.BlockBlob.PutBlockList(blockList);
var duration = DateTime.Now - model.StartTime;
float fileSizeInKb = model.Size / 1024;
string fileSizeMessage = fileSizeInKb > 1024 ? string.Concat((fileSizeInKb / 1024).ToString(CultureInfo.CurrentCulture), " MB") : string.Concat(fileSizeInKb.ToString(CultureInfo.CurrentCulture), " KB");
model.UploadStatusMessage = string.Format(CultureInfo.CurrentCulture, "File of size {0} took {1} seconds to upload.", fileSizeMessage, duration.TotalSeconds);
IAsset mediaServiceAsset = CreateMediaAsset(model);
model.AssetId = mediaServiceAsset.Id;
// Note: You need atleast 1 reserve streaming unit for dynamic packaging of encoded media. If you don't have that, you can't see video file playing.
var assetId = model.AssetId;
IAsset inputAsset = GetAssetById(assetId);
string token = string.Empty;
string uploadFileOriginalName = string.Empty;
////// Without preset (say default preset), works very well
//IJob job = context.Jobs.CreateWithSingleTask(MediaProcessorNames.AzureMediaEncoder,
// MediaEncoderTaskPresetStrings.H264AdaptiveBitrateMP4Set720p,
// inputAsset,
// "UploadedVideo-" + Guid.NewGuid().ToString().ToLower() + "-Adaptive-Bitrate-MP4",
// AssetCreationOptions.None);
//job.Submit();
//IAsset encodedOutputAsset = job.OutputMediaAssets[0];
//// XML Preset
IJob job = context.Jobs.Create(inputAsset.Name);
IMediaProcessor processor = GetLatestMediaProcessorByName("Media Encoder Standard");
string configuration = System.IO.File.ReadAllText(HttpContext.Server.MapPath("~/MediaServicesCustomPreset.xml"));
ITask task = job.Tasks.AddNew(inputAsset.Name + "- encoding task", processor, configuration, TaskOptions.None);
task.InputAssets.Add(inputAsset);
task.OutputAssets.AddNew(inputAsset.Name + "-Adaptive-Bitrate-MP4", AssetCreationOptions.None);
job.Submit();
IAsset encodedAsset = job.OutputMediaAssets[0];
// process policy & encryption
ProcessPolicyAndEncryption(encodedAsset);
// Get file name
uploadFileOriginalName = model.FileName;
// Generate Streaming URL
string smoothStreamingUri = GetStreamingOriginLocator(encodedAsset, uploadFileOriginalName);
// add jobid and output asset id in database
AzureMediaServicesContext db = new AzureMediaServicesContext();
var video = new Video();
video.RowAssetId = assetId;
video.EncodingJobId = job.Id;
video.EncodedAssetId = encodedAsset.Id;
video.LocatorUri = smoothStreamingUri;
video.IsEncrypted = useAESRestriction;
db.Videos.Add(video);
db.SaveChanges();
if (useAESRestriction)
{
token = AzureMediaAsset.GetTestToken(encodedAsset.Id, encodedAsset);
}
// Remove session
Session.Remove("CurrentFile");
// return success response
return Json(new
{
error = false,
message = "Congratulations! Video is uploaded and pipelined for encoding, check console log for after encoding playback details.",
assetId = assetId,
jobId = job.Id,
locator = smoothStreamingUri,
encrypted = useAESRestriction,
token = token
});
//if (id == model.BlockCount){CommitAllChunks(model);}
//return Json(new { error = false, isLastBlock = false, message = string.Empty, filename = fileName,filesize = videoStream.Length });
}
However this kind of solution is to rigid and not for a long term solution but the concept was there and able to meet my goal. I will just redo my code and re-create a more flexible solution.
NOTE: I am not a C# developer. Respect for the beginner like me.
I have an angular application that is uploading files using my API.
I have a bit of code that looks like this:
var url = __env.apiUrl + 'documents/' + containerName + '/' + reference;
var formData = new FormData();
var request = {
method: 'POST',
url: url,
data: formData,
headers: {
'Content-Type': undefined
}
};
formData.append('file', file);
formData.append('metadata', JSON.stringify(metadata));
return $http(request).then(function (response) {
SimpleCache.remove(__env.apiUrl + '/documents');
listDirectiveService.refresh('document');
ngNotify.set('Your document was created.');
}, notifications.handleError).finally(function () {
onComplete();
});
On my API side, the c# used to get the file looks like this:
if (!request.Content.IsMimeMultipartContent("form-data")) throw new HttpResponseException(request.CreateResponse(HttpStatusCode.UnsupportedMediaType));
Valiate(containerName, directoryName);
var filesReadToProvider = await request.Content.ReadAsMultipartAsync();
// We assume that the form data name is file and metadata respectively
var fileStream = filesReadToProvider.Contents.SingleOrDefault(m => m.Headers.ContentDisposition.Name.Equals("\"file\"", StringComparison.OrdinalIgnoreCase));
var metaDataStream = filesReadToProvider.Contents.SingleOrDefault(m => m.Headers.ContentDisposition.Name.Equals("\"metadata\"", StringComparison.OrdinalIgnoreCase));
if (fileStream == null) throw new ArgumentNullException(nameof(fileStream));
if (metaDataStream == null) throw new ArgumentNullException(nameof(metaDataStream));
This works, but the problem is the name of the ContentDisposition.
If you notice, it looks for "file" instead of file.
Does anyone know why it has the extra quotes?
I never found out why this was happening, so I just made my function like this:
public async Task<string> CreateAsync(HttpRequestMessage request, string containerName, string directoryName, string existingUrl = "")
{
if (!request.Content.IsMimeMultipartContent("form-data")) throw new HttpResponseException(request.CreateResponse(HttpStatusCode.UnsupportedMediaType));
Valiate(containerName, directoryName);
var filesReadToProvider = await request.Content.ReadAsMultipartAsync();
// We assume that the form data name is file and metadata respectively
var fileStream = filesReadToProvider.Contents.SingleOrDefault(m =>
m.Headers.ContentDisposition.Name.Equals("\"file\"", StringComparison.OrdinalIgnoreCase) ||
m.Headers.ContentDisposition.Name.Equals("file", StringComparison.OrdinalIgnoreCase));
var metaDataStream = filesReadToProvider.Contents.SingleOrDefault(m =>
m.Headers.ContentDisposition.Name.Equals("\"metadata\"", StringComparison.OrdinalIgnoreCase) ||
m.Headers.ContentDisposition.Name.Equals("metadata", StringComparison.OrdinalIgnoreCase));
if (fileStream == null) throw new ArgumentNullException(nameof(fileStream));
if (metaDataStream == null) throw new ArgumentNullException(nameof(metaDataStream));
// Upload our file
var fileBytes = await fileStream.ReadAsByteArrayAsync();
var mediaType = fileStream.Headers.ContentType.MediaType;
var friendlyFileName = fileStream.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(friendlyFileName)}";
var directory = GetDirectory(containerName, directoryName);
var fileUrl = await Upload(directory, fileName, mediaType, fileBytes);
// Add our metadata
var metadata = await GetMetadataFromMemoryStreamAsync(metaDataStream);
metadata.Add("fileName", friendlyFileName);
metadata.Add("directory", directoryName);
metadata.Add("created", DateTime.UtcNow.ToString(CultureInfo.InvariantCulture));
await AddFileMetaDataAsync(fileUrl, metadata);
// Delete any existing file
if (!string.IsNullOrEmpty(existingUrl) && fileUrl != existingUrl) await DeleteAsync(containerName, directoryName, existingUrl);
return fileUrl;
}
Just to cover all bases. It isn't the best, but it should work fine.
I have launched a new application at work. We create letters using OpenXML which works flawlessly on Dev, but on production the solution is not returning.
$("#createLetter").on("click", CreateLetter);
function CreateLetter() {
$.ajax({
type: "POST",
url: "/Letters/CreateLetter",
data: {
EntityType: "#overview.EntityType",
EntityId: #overview.EntityId,
Recipient: $("#Recipient").val(),
TemplatesLocation: $("#templatePath").val(),
SaveAs: $("#saveAs").val()
},
async: false,
success: openLetter
});
}
function openLetter(data) {
openFile(data);
window.location.reload(false);
}
Controller Method:
[ValidateInput(false)]
[HttpPost]
public JsonResult CreateLetter(CreateLetter input)
{
Recipient obj = logic.SplitRecipientInput(input.Recipient);
input.RecipientId = obj.RecipientId;
input.RecipientType = obj.Type;
input.Username = Helpers.GetLoggedInUser();
var x = logic.CreateLetter(input);
if (x.Success == 1)
{
return Json(x.Data, JsonRequestBehavior.AllowGet);
}
else
{
return Json("Error", JsonRequestBehavior.AllowGet);
}
}
Consumption Logic:
public CreatedLetter CreateLetter(CreateLetter input)
{
CreatedLetter response = new CreatedLetter();
Parameters.Add("TemplatePath", GetApiValue(input.TemplatesLocation));
Parameters.Add("EntityType", GetApiValue(input.EntityType));
Parameters.Add("EntityId", GetApiValue(input.EntityId));
Parameters.Add("RecipientId", GetApiValue(input.RecipientId));
Parameters.Add("RecipientType", GetApiValue(input.RecipientType));
Parameters.Add("Username", GetApiValue(input.Username));
Parameters.Add("SaveAs", GetApiValue(input.SaveAs));
response = Api.WebRequest<CreatedLetter>("CreateLetters", Parameters, Method.POST) as CreatedLetter;
return response;
}
API Controller method:
[ActionName("CreateLetter")]
[HttpPost]
public ApiResponse CreateLetter(LetterCreateInput input)
{
try
{
LetterTemplateLogic logic = new LetterTemplateLogic();
Random r = new Random();
var randomId = r.Next(100000, 999999);
string fileName = string.Format("{0} - {1}", randomId, input.SaveAs);
input.SaveAs = fileName;
// Get all objects for Letter
List<object> objs = logic.TemplateObjectsRetriever(input.EntityId, input.EntityType, input.Username, randomId);
objs.Add(logic.GetRecipient(input.RecipientId, input.RecipientType));
// Get save location
string saveLocation = logic.LetterLocationResolver(input.EntityId, input.EntityType);
var data = logic.OpenAndUpdateTemplate(objs, input.TemplatePath, input.SaveAs, saveLocation, FileExtension);
AttachmentInput letterAttachment = new AttachmentInput();
letterAttachment.Id = input.EntityId;
letterAttachment.FileTypeId = 1;
letterAttachment.Path = data;
letterAttachment.Username = input.Username;
letterAttachment.Description = fileName;
letterAttachment.EntityType = input.EntityType;
logic.InsertLetterAttachment(letterAttachment);
return ApiResponse.Return(data);
}
catch (Exception ex)
{
return ApiResponse.Error(ex);
}
}
This returns literally nothing on production. No errors in the console, no errors from the API which logs erroneous calls. I was hoping someone could make a suggestion?
Thanks.
I, am using angular 5, with asp.net core 2.0. I, am trying to upload the file to the server. The code update the file to the server. But with 0 kb of data and sometime it upload the file.
The file size is not large. Its in KB.
Here is the Angular code
public QuestionPostHttpCall(_questionPhotoVM: QuestionPhotoViewModel): Observable<GenericResponseObject<QuestionPhotoViewModel[]>> {
const formData: FormData = new FormData();
formData.append('FileUpload', _questionPhotoVM.FileUpload);
formData.append('QuestionText', _questionPhotoVM.questionText);
formData.append('QuestionId', _questionPhotoVM.questionId);
const headers = new HttpHeaders().set('enctype', 'multipart/form-data');
return this._httpClientModule.post<GenericResponseObject<QuestionPhotoViewModel[]>>(this.questionPhotoUrl, formData);
}
In the controller I, can receive the file.
Here is the controller method
[HttpPost]
public JsonResult QuestionPhotoPost(IFormFile FileUpload, string QuestionText, Guid? QuestionId)
{
string TempFileName = string.Empty;
var directiveToUpload = Path.Combine(_environment.WebRootPath, "images\\UploadFile");
var http = HttpRequestExtensions.GetUri(Request);
QuestionViewModel model = new QuestionViewModel();
try
{
if (FileUpload != null)
{
TempFileName = FileUpload.FileName;
CheckFileFromFrontEnd();
}
}
catch (Exception exception)
{
}
void CheckFileFromFrontEnd()
{
if (FileUpload != null)
{
if (!System.IO.Directory.Exists(directiveToUpload))
{
System.IO.Directory.CreateDirectory(directiveToUpload);
}
if (System.IO.File.Exists(string.Format("{0}\\{1}\\{2}", _environment.WebRootPath, "images\\UploadFile", FileUpload.FileName)))
{
TempFileName = Guid.NewGuid().ToString() + FileUpload.FileName;
}
model.PictureUrl = string.Format("{0}://{1}/{2}/{3}/{4}", http.Scheme, http.Authority, "images", "UploadFile", TempFileName);
SaveFileToServer(TempFileName);
}
}
void SaveFileToServer(string FileName)
{
if (FileUpload.Length > 0)
{
using (var stream = new FileStream(Path.Combine(directiveToUpload, FileName), FileMode.Create))
{
FileUpload.CopyToAsync(stream);
}
}
}
return Json(genericResponseObject);
}
The file is uploaded to the server. But some time it upload with 0 byte and sometime it upload correctly.
The resolution of file is 570 X 400 and size of file 197KB
Where I, am doing wrong?? Please anyone let me know. Do, I need to specify max byte in somewhere ??
Your problem is that you are using an asynchronous function and not awaiting it.
You are using ASP.NET Core so you should (read "must") use the async-all-the-way pattern:
[HttpPost]
public async Task<JsonResult> QuestionPhotoPost(IFormFile FileUpload, string QuestionText, Guid? QuestionId)
{
string TempFileName = string.Empty;
var directiveToUpload = Path.Combine(_environment.WebRootPath, "images\\UploadFile");
var http = HttpRequestExtensions.GetUri(Request);
QuestionViewModel model = new QuestionViewModel();
try
{
if (FileUpload != null)
{
TempFileName = FileUpload.FileName;
await CheckFileFromFrontEndAsync();
}
}
catch (Exception exception)
{
}
async Task CheckFileFromFrontEndsync()
{
if (FileUpload != null)
{
if (!System.IO.Directory.Exists(directiveToUpload))
{
System.IO.Directory.CreateDirectory(directiveToUpload);
}
if (System.IO.File.Exists(string.Format("{0}\\{1}\\{2}", _environment.WebRootPath, "images\\UploadFile", FileUpload.FileName)))
{
TempFileName = Guid.NewGuid().ToString() + FileUpload.FileName;
}
model.PictureUrl = string.Format("{0}://{1}/{2}/{3}/{4}", http.Scheme, http.Authority, "images", "UploadFile", TempFileName);
await SaveFileToServerAsync(TempFileName);
}
}
async Task SaveFileToServerAsync(string FileName)
{
if (FileUpload.Length > 0)
{
using (var stream = new FileStream(Path.Combine(directiveToUpload, FileName), FileMode.Create))
{
await FileUpload.CopyToAsync(stream);
}
}
}
return Json(genericResponseObject);
}
To make the code more readable, I'd move those inline functions to outside, though.