I have the following code for uploading file:
var formData = new FormData();
var file = document.getElementById("file").files[0];
formData.append("file", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", "UploadFileServer.axd", false);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.setRequestHeader("Pragma", "no-cache");
xhr.setRequestHeader("Cache-Control", "no-cache, must-revalidate");
xhr.addEventListener('readystatechange', function(e) {
if (this.readyState === 4) {
if (this.status == 200 && this.response != null) {
var clientResponse = JSON.parse(this.response);
if (clientResponse.Success) {
//alert 1
}
else if (!clientResponse.Success) {
//alert 2
}
else {
//SOME ERROR!
}
}
}
});
xhr.send(formData);
Using IE10 everything works fine.
Using Chrome, I get no files on server side:
UploadFileServer.axd:
void IHttpHandler.ProcessRequest(HttpContext ctx)
{
OutputDebugString("Enter process req");
HttpFileCollection uploadFile = ctx.Request.Files;
if (uploadFile.Count > 0)
{
//do something
ctx.Response.ContentType = "application/json; charset=utf-8";
ctx.Response.Write(uploadFileResponse);
}
}
UploadFile.Count = 0
any ideas why is it empty?
In some browsers the uploaded file doesn't arrive at the server in the Request.Files collection when using xmlHttpRequest, but in the body of the request.
I would suggest something like:
if (Request.Files.AllKeys.Any())
{
var key = Request.Files.AllKeys.First();
fullSizeImage = new WebImage(Request.Files[key].InputStream);
}
else
{
fullSizeImage = new WebImage(Request.InputStream);
}
Or whatever you want to do with the image :)
Related
I have angular project as my client side and .Net 6 web api project as my backend. I am still new to both technologies. I am creating a website and there is a functionality that I am trying to add and haven't been successful so far. I want to upload images into a .Net web api project images folder using angular. I also want to later access those images from angular project. I want to store the path of the image files in the database. I have tried to check for the code on the internet without success. Your assistance will be appreciated.
First, submit your's files from frontend with FormData
postWithFile(url: string, obj: any, files: File[]) {
let cloneHeader: any = {};
let options: any = {
headers: new HttpHeaders(cloneHeader),
observe: 'response',
responseType: 'json'
};
let formData: FormData = new FormData();
if (typeof obj == 'object') { // obj is external submit data
formData.append('data', JSON.stringify(obj));
} else {
formData.append('data', obj);
}
if (files && files.length > 0) {
files.forEach((ds, index) => {
formData.append('file_' + index, ds, ds.name);
});
}
return this._http
.post(this.host + url, formData, options)
.pipe(map((res: any) => {
return res.body;
}));
}
And backend handle request with HttpContext.Current.Request.Files, save images to server and store path of images in database
[HttpPost]
public ResponseMessage<bool?> UploadImages()
{
var response = new ResponseMessage<bool?>();
try
{
if (!Request.Content.IsMimeMultipartContent())
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
ExternalDataModel model = MessageConvert.DeserializeObject<ExternalDataModel>(HttpContext.Current.Request["data"]); // obj in frontend
//
List<string> listImages = new List<string>();
DateTime now = DateTime.Now;
string buildPath = $"{string.Format("{0:00}", now.Year)}\\{string.Format("{0:00}", now.Month)}\\{string.Format("{0:00}", now.Day)}"; // change by your's folder path
foreach (string file in HttpContext.Current.Request.Files)
{
var fileContent = HttpContext.Current.Request.Files[file];
int fileLength = fileContent.ContentLength;
if (fileContent != null && fileLength > 0)
{
var stream = fileContent.InputStream;
byte[] imgByteArray;
using (MemoryStream memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
imgByteArray = memoryStream.ToArray();
}
string fileName = $"format_file_name_if_need_{fileContent.FileName}";
string RelativeFolder = $"{buildPath}";
string AbsoluteFolder = Path.Combine("FOLDER_IN_SERVER_FULL_PATH", RelativeFolder);
if (!Directory.Exists(AbsoluteFolder))
{
Directory.CreateDirectory(AbsoluteFolder);
}
string pathSave = Path.Combine(RelativeFolder, fileName);
FileHelper.SaveFileFromBinaryArray(pathSave, imgByteArray);
listImages.Add(pathSave);
}
}
// model.listImages = listImages; // assign to model to save to DB
//
// var data = _bus.uploadImage(model);
// if (data)
// {
// response.Data = true;
// response.MessageCode = MessageCodes.UpdateSuccessfully;
// }
}
catch (Exception ex)
{
response.MessageCode = ex.Message;
}
return response;
}
I am working on a application that has a button, when that button is clicked it calls a web api GET method. This method takes files and creates a zip folder using System.IO.Compression. This part works great. I see the folder it creates and I am able to open / extract that folder with its files. The problem i have is when the file gets returned to the browser and the browser downloads the file I get the following error: " The Compressed (zipped) folder '...pathToTheDownloadedFile.zip' is invalid. I don't understand what I am doing wrong. All other non-zipped files download and open fine.
Here is my web api GET method:
[HttpGet]
[Route("api/OrderManager/ExtractAllDocuments/{orderNum}/{mappingId}/")]
public HttpResponseMessage ExtractAllDocuments(int orderNum, int mappingId)
{
try
{
var docPath = #"" + HttpContext.Current.Server.MapPath("MyPath");
var files = Directory.GetFiles(docPath);
string zipName = #"supportingdocuments_order" + orderNum + ".zip";
FileStream zipToOpen = new FileStream(docPath + zipName, FileMode.Create);
using (var zipArchive = new ZipArchive(zipToOpen, ZipArchiveMode.Create))
{
foreach (var fPath in files)
{
if (!fPath.Contains(".zip"))
{
zipArchive.CreateEntryFromFile(fPath, Path.GetFileName(fPath), CompressionLevel.Fastest);
}
}
}
zipToOpen.Close();
//At this point the directory is created and saved as it should be
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
var fullZipPath = docPath + zipName;
byte[] bytes = File.ReadAllBytes(fullZipPath);
response.Content = new ByteArrayContent(bytes);
response.Content.Headers.ContentLength = bytes.LongLength;
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = zipName;
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(MimeMapping.GetMimeMapping(zipName));
return response;
}
catch (Exception e)
{
var b = e.Message;
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.NotFound);
response.ReasonPhrase = string.Format("Failed To Extract Files");
throw new HttpResponseException(response);
}
}
Here is my $.ajax call:
$.ajax({
url: 'myApiUrl',
method: 'GET'
}).done(function (data, status, xmlHeaderRequest) {
var downloadLink = document.createElement('a');
var blob = new Blob([data],
{
type: xmlHeaderRequest.getResponseHeader('Content-Type')
});
var url = window.URL || window.webkitURL;
var downloadUrl = url.createObjectURL(blob);
var fileName = '';
// get the file name from the content disposition
var disposition = xmlHeaderRequest.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g, '');
}
}
// Blob download logic taken from: https://stackoverflow.com/questions/16086162/handle-file-download-from-ajax-post
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007" and "Access Denied" error.
window.navigator.msSaveBlob(blob, fileName);
} else {
if (fileName) {
if (typeof downloadLink.download === 'undefined') {
window.location = downloadUrl;
} else {
downloadLink.href = downloadUrl;
downloadLink.download = fileName;
document.body.appendChild(downloadLink);
downloadLink.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () {
url.revokeObjectURL(downloadUrl);
},
100);
}
}).fail(function (data) {
$.notify({
// options
message:
'<i class="fas fa-exclamation-circle"></i> Could not download all documents.'
},
{
// settings
type: 'danger',
placement: {
from: "top",
align: "left"
},
delay: 2500,
z_index: 10031
});
});
I'm at a total and complete loss on this one. Thank you in advance for any help you can provide as it is greatly appreciated.
So after searching I have found a solution that works. $.ajax doesn't like binary data and thinks everything is UTF-8 text encoding apparently. So I used an XMLHttpRequest (xhr). For those that need it below is as copy of the c# and the javascript solution.
C# WebApi Controller:
public HttpResponseMessage ExtractAllDocuments(int orderNum, int mappingId)
{
try
{
var docPath = #"" + HttpContext.Current.Server.MapPath("myPath");
var files = Directory.GetFiles(docPath);
string zipName = #"Supporting-Documents-Order-" + orderNum + ".zip";
FileStream zipToOpen = new FileStream(docPath + zipName, FileMode.Create);
using (var zipArchive = new ZipArchive(zipToOpen, ZipArchiveMode.Create))
{
foreach (var fPath in files)
{
if (!fPath.Contains(".zip"))
{
zipArchive.CreateEntryFromFile(fPath, Path.GetFileName(fPath), CompressionLevel.Fastest);
}
}
}
zipToOpen.Close();
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(new FileStream(docPath + zipName, FileMode.Open, FileAccess.Read));
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = zipName;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
return response;
}
catch (Exception e)
{
var b = e.Message;
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.NotFound);
response.ReasonPhrase = string.Format("Failed To Extract Files");
throw new HttpResponseException(response);
}
}
Front End JavaScript:
function extractAllDocuments() {
let xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange', function (e) {
if (xhr.readyState == 2 && xhr.status == 200) {
// Download is being started
}
else if (xhr.readyState == 3) {
// Download is under progress
}
else if (xhr.readyState == 4) {
//operation done
// Create a new Blob object using the response data of the onload object
var blob = new Blob([this.response], { type: 'application/zip' });
//Create a link element, hide it, direct it towards the blob, and then 'click' it programatically
let a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
//Create a DOMString representing the blob and point the link element towards it
let url = window.URL.createObjectURL(blob);
a.href = url;
// get the file name from the content disposition
var fileName = '';
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) {
fileName = matches[1].replace(/['"]/g, '');
}
}
a.download = fileName;
//programatically click the link to trigger the download
a.click();
//Remove From Server
$.ajax({
url: 'myUrl',
method: 'DELETE'
}).done(function (data) {
}).fail(function (data) {
});
setTimeout(function () {
window.URL.revokeObjectURL(url);
}, 60 * 1000);
} else if (xhr.status == 400){
$.notify({
// options
message:
'<i class="fas fa-exclamation-circle"></i> Could not download all documents.'
},
{
// settings
type: 'danger',
placement: {
from: "top",
align: "left"
},
delay: 2500,
z_index: 10031
});
}
});
//set the request type to post and the destination url to '/convert'
xhr.open('GET', 'MyUrl');
//set the reponse type to blob since that's what we're expecting back
xhr.responseType = 'blob';
xhr.send();
return false;
}
I'm trying to generate excel file from my database and download the file from my website but when I open the excel file the error "can not open the file because file format or file extension is not valid." has occurred.
So, This is my code for doing this.
Here is my script:
$(document).ready(function () {
$("#btnExportExcel").click(function (e) {
e.preventDefault();
const deferred = $.Deferred();
var paymentType = $("#transactionTypeDropdown").val();
var paymentStatus = $("#paymentStatusDropdown").val();
var merchantName = $("#merchantNameDropdown").val();
var dateTime = $("#reservation").val().split(" ");
var refNo = $("#refNoInput").val();
var terminalId = $("#terminalID").val();
$.ajax({
type: "POST",
crossOrigin: true,
url: "/api/Transaction/ExportExcel",
headers: {
Accept: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
},
data: {
"Date_1": dateTime[0],
"Date_2": dateTime[2],
"PaymentType": paymentType,
"Status": paymentStatus,
"Outtrade": refNo,
"Merchant": merchantName,
"TerminalID": terminalId
},
success: function (result) {
if (dateTime[0] == dateTime[2]) {
filename = "Transaction_Detail_" + dateTime[0].replace(/\//g, '-') + ".xlsx";
}
else {
filename = "Transaction_Detail_" + dateTime[0].replace(/\//g, '-') + " - "
+ dateTime[2].replace(/\//g, '-') + ".xlsx";
}
var uri = 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,' + result;
var link = document.createElement("a");
link.href = uri;
link.style = "visibility:hidden";
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
},
error: function (jqXHR, exception) {
getErrorMessage(jqXHR, exception);
}
});
return deferred.promise();
});
});
Here is my C# API:
public class TransactionController : ApiController
{
[AllowAnonymous]
[HttpPost]
[Route("api/Transaction/ExportExcel")]
public HttpResponseMessage ExportExcel(TransactionSearchReq req)
{
TransactionMgr transaction = new TransactionMgr();
List<TransactionRecordRes> transactionList = new List<TransactionRecordRes>();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
MediaTypeHeaderValue mediaType = MediaTypeHeaderValue.Parse("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
byte[] fileContents;
string fileName;
try
{
// Get transaction records
transactionList = transaction.GetSearchTransactionRecord(req);
if (transactionList.Count() > 0)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (var package = new ExcelPackage())
{
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
// I put data to worksheet here.
fileContents = package.GetAsByteArray();
}
if (fileContents == null || fileContents.Length == 0)
{
response = Request.CreateResponse(HttpStatusCode.InternalServerError);
response.Content = new StringContent("Export file error.", Encoding.Unicode);
return response;
}
else
{
if (string.Compare(req.Date_1, req.Date_2) == 0)
{
fileName = string.Format("Transaction_Detail_{0}.xlsx", req.Date_1.Replace('/', '-'));
}
else
{
fileName = string.Format("Transaction_Detail_{0} - {1}.xlsx", req.Date_1.Replace('/', '-'), req.Date_2.Replace('/', '-'));
}
MemoryStream memoryStream = new MemoryStream(fileContents);
response.Content = new StreamContent(memoryStream);
response.Content.Headers.ContentType = mediaType;
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment") { FileName = fileName };
return response;
}
}
else
{
response = Request.CreateResponse(HttpStatusCode.InternalServerError);
response.Content = new StringContent("Export file error.", Encoding.Unicode);
return response;
}
}
catch (Exception ex)
{
response = Request.CreateResponse(HttpStatusCode.InternalServerError);
response.Content = new StringContent("Export file error.", Encoding.Unicode);
return response;
}
}
}
Where I'm going wrong ?
I'm downloading xml from: https://ims.data.gov.il/sites/default/files/xml/imslasthour.xml
from Desktop application
The function for download is
private static XDocument LoadDoc(string url)
{
Debug.Assert(!string.IsNullOrWhiteSpace(url));
XDocument doc = null;
var request = WebRequest.Create(url) as HttpWebRequest;
request.Proxy = null;
request.UseDefaultCredentials = true;
var cc = new CookieContainer();
request.CookieContainer = cc;
using (var response = request.GetResponse() as HttpWebResponse)
{
using (var sr = new StreamReader(response.GetResponseStream()))
{
var content = sr.ReadToEnd();
try
{
doc = XDocument.Parse(content);
}
catch (XmlException e)
{
Log.Error(e.Message);
}
}
}
return doc;
}
In all machines application works properly.
When it was run on Azure virtual machine, instead of xml file it returned:
<head>
<script>
Challenge=243009;
ChallengeId=196151745;
GenericErrorMessageCookies="Cookies must be enabled in order to view this page.";
</script>
<script>
function test(var1)
{
var var_str=""+Challenge;
var var_arr=var_str.split("");
var LastDig=var_arr.reverse()[0];
var minDig=var_arr.sort()[0];
var subvar1 = (2 * (var_arr[2]))+(var_arr[1]*1);
var subvar2 = (2 * var_arr[2])+var_arr[1];
var my_pow=Math.pow(((var_arr[0]*1)+2),var_arr[1]);
var x=(var1*3+subvar1)*1;
var y=Math.cos(Math.PI*subvar2);
var answer=x*y;
answer-=my_pow*1;
answer+=(minDig*1)-(LastDig*1);
answer=answer+subvar2;
return answer;
}
</script>
<script>
client = null;
if (window.XMLHttpRequest)
{
var client=new XMLHttpRequest();
}
else
{
if (window.ActiveXObject)
{
client = new ActiveXObject('MSXML2.XMLHTTP.3.0');
};
}
if (!((!!client)&&(!!Math.pow)&&(!!Math.cos)&&(!![].sort)&&(!![].reverse)))
{
document.write("Not all needed JavaScript methods are supported.<BR>");
}
else
{
client.onreadystatechange = function()
{
if(client.readyState == 4)
{
var MyCookie=client.getResponseHeader("X-AA-Cookie-Value");
if ((MyCookie == null) || (MyCookie==""))
{
document.write(client.responseText);
return;
}
var cookieName = MyCookie.split('=')[0];
if (document.cookie.indexOf(cookieName)==-1)
{
document.write(GenericErrorMessageCookies);
return;
}
window.location.reload(true);
}
};
y=test(Challenge);
client.open("POST",window.location,true);
client.setRequestHeader('X-AA-Challenge-ID', ChallengeId);
client.setRequestHeader('X-AA-Challenge-Result',y);
client.setRequestHeader('X-AA-Challenge',Challenge);
client.setRequestHeader('Content-Type' , 'text/plain');
client.send();
}
</script>
</head>
<body>
<noscript>JavaScript must be enabled in order to view this page.</noscript>
</body>
</HTML>
response.StatusDescription id "OK"
Browser in Azure returns proper xml. If community can help me to cope with this problem?
I have Angular SPA which downloads a file from ASP.NET Web API 2 using the following approach:
Angular Code
$scope.downloadFile = function(httpPath) {
// Use an arraybuffer
$http.get(httpPath, { responseType: 'arraybuffer' })
.success( function(data, status, headers) {
var octetStreamMime = 'application/octet-stream';
var success = false;
// Get the headers
headers = headers();
// Get the filename from the x-filename header or default to "download.bin"
var filename = headers['x-filename'] || 'download.bin';
// Determine the content type from the header or default to "application/octet-stream"
var contentType = headers['content-type'] || octetStreamMime;
try
{
// Try using msSaveBlob if supported
console.log("Trying saveBlob method ...");
var blob = new Blob([data], { type: contentType });
if(navigator.msSaveBlob)
navigator.msSaveBlob(blob, filename);
else {
// Try using other saveBlob implementations, if available
var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
if(saveBlob === undefined) throw "Not supported";
saveBlob(blob, filename);
}
console.log("saveBlob succeeded");
success = true;
}
catch(ex)
{
console.log("saveBlob method failed with the following exception:");
console.log(ex);
}
if(!success)
{
// Get the blob url creator
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
if(urlCreator)
{
// Try to use a download link
var link = document.createElement('a');
if('download' in link)
{
// Try to simulate a click
try
{
// Prepare a blob URL
console.log("Trying download link method with simulated click ...");
var blob = new Blob([data], { type: contentType });
var url = urlCreator.createObjectURL(blob);
link.setAttribute('href', url);
// Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
link.setAttribute("download", filename);
// Simulate clicking the download link
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
console.log("Download link method with simulated click succeeded");
success = true;
}
catch(ex) {
console.log("Download link method with simulated click failed with the following exception:");
console.log(ex);
}
}
if(!success)
{
// Fallback to window.location method
try
{
// Prepare a blob URL
// Use application/octet-stream when using window.location to force download
console.log("Trying download link method with window.location ...");
var blob = new Blob([data], { type: octetStreamMime });
var url = urlCreator.createObjectURL(blob);
window.location = url;
console.log("Download link method with window.location succeeded");
success = true;
} catch(ex) {
console.log("Download link method with window.location failed with the following exception:");
console.log(ex);
}
}
}
}
if(!success)
{
//Fallback to window.open method
console.log("No methods worked for saving the arraybuffer, using last resort window.open");
window.open(httpPath, '_blank', '');
}
})
.error(function(data, status) {
console.log("Request failed with status: " + status);
// Optionally write the error out to scope
$scope.errorDetails = "Request failed with status: " + status;
});
};
httpPath is a url of my Web API Controller. The controller has the following code:
Web API Code
[HttpGet]
[Authorize]
public async Task<HttpResponseMessage> DownloadItems(string path)
{
try
{
Stream stream = await documentsRepo.getStream(path);
HttpResponseMessage result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = "document.zip",
};
result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentLength = stream.Length;
return result;
}
catch (Exception e)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, e);
}
}
The above setup works perfectly well in all browsers (a .zip file is downloaded), except IE11.
For unknown reason, IE11 downloads the file without .zip extension
Any idea what could be wrong with my API Controller?