Read a file and display its data and then upload it. : Angularjs - angularjs

I need to read a xls file and display its data onto the client and then if the user selects, upload it to the server.
i have till now tried :
var f = document.getElementById('file').files[0],
r = new FileReader();
r.onloadend = function(e){
var data = e.target.result; console.log(data);
//send you binary data via $http or $resource or do anything else with it
}
r.readAsDataURL(f);
}
But now i am getting data as :
data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base ....\
which is a downloadable file.
How can i read the data of a file on the client side using Angularjs and then selectively upload and save it onto the server.

Related

s it possible to implement file upload function?

We are implementing file download function.
UI, service API server, and file server (external server) exist, and I cannot access the file server. (Code cannot be changed)
Currently, a file is downloaded by requesting UI -> FileServer.
I want to configure UI -> Service API -> File Server for multiple file downloads and exception handling.
As the service API operates in the middle, the final value of http that the client receives is different, but I don't know why.
Existing file servers returned an ArrayBuffer,
It was changed to a long string in String format while going through my service API server.
// my Server -> fileServer (GET Http Request)
// setting header...
// setting uri...
HttpEntity req = new HttpEntity<>(httpHeaders);
RestTemplate rt = new RestTemplate();
HttpEntity<byte[]> result = rt.exchange(
uri,
HttpMethod.GET,
req,
byte[].class
);
byte[] blob = result.getBody();
The reason why I received byte[] through result.getBody() is that I thought that the return value of the file server would be a file, and it would be a byte[] type in Java.
// react (client code)
// blobFromApi = The result my server responded
let blob = new Blob([blobFromApi], { type:'image/png' });
if (navigator.userAgent.match('CriOS')) {
let reader = new FileReader();
reader.onload = function (e) {
window.location.href = reader.result;
};
reader.readAsDataURL(blob);
} else {
FileSaver.saveAs(blob, file.file_name);
}
});
In conclusion, is it possible to implement a file download function in my current situation?

Download xlsx file passed from nodejs to frontend angularjs

I have a JSON array of objects that is a result of a function in nodejs. I use json2xls to convert that to an excel file, and it downloads to the server (not in a public folder, and is formatted correctly in Excel).
I would like to send a response to the frontend with the json results (to display as a preview) and show a button they can click to download the xlsx file OR display the JSON results and automatically download the file.
But I can't get it, and I've tried so many things I'm going crazy.
My controller code (the part that creates the xls file):
var xls = json2xls(results,{});
var today = (new Date()).toDateString('yyyy-mm-dd');
var str = today.replace(/\s/g, '');
var fileName = "RumbleExport_"+ str +".xlsx";
var file = fs.writeFileSync(fileName,xls,'binary');
res.download('/home/ubuntu/workspace/'+file);
The frontend controller:
vm.exportData = function(day, event, division) {
console.log('Export registrations button pressed.', vm.export);
//send the search parameters to the backend to run checks
$http.post('/api/exportData', vm.export).then(function(response){
vm.results = response.data;
console.log("Results",response);
vm.exportMessage = "Found " + vm.results.length + " registrations.";
})
.catch(function(error){
vm.exportError = error.data;
});
};
The view:
//display a button to download the export file
<a target="_self" file="{{vm.results}}" download="{{vm.results}}">Download Export File</a>
Someone please put me out of my misery. All the classes I've taken and none have covered this.
I FINALLY got it! And since I searched forever trying to make something work, I'll share the answer:
On the backend:
//save the file to the public/exports folder
var file = fs.writeFileSync('./public/exports/'+fileName,xls,'binary');
//send the results to the frontend
res.json(200).json({results:results, fileName: fileName});
On the frontend, use HTML to download a link to the file:
<a href="exports/{{fileName}}" download>Save File</a>

AngularJS GET receives empty reply in Chrome but not in Fiddler

I'm implementing file download using AngularJS and WCF. My back-end is a .NET project hosted in IIS. The file is serialized as an array of bytes and then on the client side I utilize the File API to save the content.
To simplify the problem, back-end is like:
[WebInvoke(Method = "GET", UriTemplate = "FileService?path={path}")]
[OperationContract]
public byte[] DownloadFileBaseOnPath(string path)
{
using (var memoryStream = new MemoryStream())
{
var fileStream = File.OpenRead(path);
fileStream.CopyTo(memoryStream);
fileStream.Close();
WebOperationContext.Current.OutgoingResponse.Headers["Content-Disposition"] = "attachment; filename=\"Whatever\"";
WebOperationContext.Current.OutgoingResponse.ContentType = "application/octet-stream"; // treat all files as binary file
return memoryStream.ToArray();
}
}
And on client side, it just sends a GET request to get those bytes, converts in into a blob and save it.
function sendGetReq(url, config) {
return $http.get(url, config).then(function(response) {
return response.data;
});
}
Save the file then:
function SaveFile(url) {
var downloadRequest = sendGetReq(url);
downloadRequest.then(function(data){
var aLink = document.createElement('a');
var byteArray = new Uint8Array(data);
var blob = new Blob([byteArray], { type: 'application/octet-stream'});
var downloadUrl = URL.createObjectURL(blob);
aLink.setAttribute('href', downloadUrl);
aLink.setAttribute('download', fileNameDoesNotMatter);
if (document.createEvent) {
var event = document.createEvent('MouseEvents');
event.initEvent('click', false, false);
aLink.dispatchEvent(event);
}
else {
aLink.click();
}
setTimeout(function () {
URL.revokeObjectURL(downloadUrl);
}, 1000); // cleanup
});
}
This approach works fine with small files. I could successfully download files up to 64MB. But when I try to download a file larger than 64MB, the response.body is empty in Chrome. I also used Fiddler to capture the traffic. According to Fiddler, Back-end has successfully serialized the byte array and returned it. Please refer to the screenshot below.
In this example, I was trying to download a 70MB file:
And the response.data is empty:
Any idea why this is empty for file over 70MB? Though the response itself is more than 200MB, I do have enough memory for that.
Regarding to the WCF back-end, I know I should use Stream Mode when it comes to large files. But the typical use of my application is to download files less than 10MB. So I hope to figure this out first.
Thanks
Answer my own question.
Honestly I don't know what's going wrong. The issue still persists if I transfer it as a byte array. I eventually gave up this approach by returning a stream instead. Then on the client side, adding the following configuration
{responseType : blob}
and save it as a blob.

File upload using AngularJS -> .NET Web Api 2 -> SQL server

I'm looking for a solution where I can upload any file to SQL server from an AngularJS frontend to .Net Web Api 2 and straight to SQL Server Database. I've done some research and for angularjs i'm mainly looking at ng-file-upload. my problem is most of the solutions that i've looked at saves the file into a temp folder. I'm not sure if it's possible but I want it straight to an SQL server table.
I've seen some solutions where it converts the file into a byte array which can be saved to an SQL table but I'm not sure how to do this in a .NET web api 2 and from an angularjs front end. thank you in advance.
Don't save files to SQL server--that's not what it's for. See this answer: In MVC4, how do I upload a file (an image) to SQL Server that's part of my domain model? And this answer: Storing files in SQL Server
Uploading files in angular is easy. Do it like this:
Controller
$scope.uploadFile = function() {
//get the filename from the <input type='file'>
//angular doesn't allow attaching ngModel to file input
var fileInput = document.getElementById("myInputId");
//check if there's a file
if(fileInput.files.length === 0) return;
//you cannot send a file as JSON because json is in the string format
//for fileuploads, you must send as a FormData() object
//C# accepts HttpPostedFileBase as the file argument
var file = fileInput.files[0];
//put the file in a new formdata object
var payload = new FormData();
payload.append("file", file);
//upload file to C# controller
$http.post("path/to/C#/controller", payload, {
//you **need** to specify these options, without them upload does not work
transformRequest: angular.identity,
headers: { "Content-Type": undefined }
}).then(function(data) {
//success
}, function(error) {
//error
});
}
C#/ASP.NET
[WebMethod]
public string UploadFile(HttpPostedFileBase file) {
//access the file object here
var inputStream = file.InputStream;
var fileName = Path.GetFileName(file.FileName);
try
{
file.SaveAs("local/path" + fileName);
}
catch (IOException exc)
{
return "Error: " + exc.Message;
}
return "success";
}

Is it possible to resend image url received from server back to it as an image after processing

I have a remote server which has profile data and an image and when I retrieve it, I get the image url, which I can display using the <img> tag, by using the url.
When I have to modify the details, I send a new image, for which I upload a new image using a small AngularJS function and send the whole data using formData and http request.
But, out of curiosity, I was wondering whether there is any way to send an object of the same image using the url I received from the server.
Another reason I thought of it was that I was thinking of maybe changing its dimensions,etc.
Just in case if I ever needed to generate a thumbnail of the image of a smaller size in future.
Solved it myself by looking around and generating a canvas from the url, through dataURI by using the function :
var byteString = atob(dataURI.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
var blob= new Blob([ab], { type: 'image/jpeg' });
to create a blob to send the image back after scaling(was required).

Resources