Download an xlsx file with reactJS: Excel can not open file - javascript

I'm trying to download an xlsx file with reactJS but i'm receiving this message when i try to open my file after download:
"Excel can not open file 'file.xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the file format"
Here's the frontend code:
const REST_DOWNLOAD_URL = REST_URL + '/token';
Rest.ajaxPromise('GET', REST_DOWNLOAD_URL).then(function (res) {
var FILE_URL = "/supermarket/token/" + res;
Rest.ajaxPromise('GET', FILE_URL).then(function (my_file) {
let blob = new Blob([my_file._body], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8' });
if (navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, 'file.xlsx');
} else {
let link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.setAttribute('download', 'file.xlsx');
document.body.appendChild(link);
link.download = '';
link.click();
document.body.removeChild(link);
}
});
});
Why am i getting this error? Please somebody help me, i'm stuck on this for 3 weeks
[EDIT 1]
The file that i'm trying to download is build on backend, basically i get the values on database and use the Apache poi workbook to create the excel sheet. I will show you the mainly parts of the code:
1) This method is called by frontend on the first GET requisition of frontend and aims to prepare the file before the download. Is very simple, just create a token (buildToken()) and associate a temp file with this token (createTempFile(randomBackendToken)). The temp file is filled with what i get on my database (createFile(os))
#RequestMapping(value = "/token", method = RequestMethod.GET)
public String returnToken() throws IOException {
String randomBackendToken = tokenGenerator.buildToken();
OutputStream os = tokenGenerator.createTempFile(randomBackendToken);
tokenGenerator.createFile(os);
return randomBackendToken;
}
2) The method where i create the temp file:
public OutputStream createTempFile(String randomBackendToken) throws IOException {
OutputStream os = null;
File file = File.createTempFile(randomBackendToken, ".xlsx");
os = new FileOutputStream(file);
return os;
}
3) The method where i receive the empty temp file and fills with my data on database:
public void createFile(OutputStream os) throws IOException {
List<Supermakets> supermarkets = service.findAllSupermarkets();
Workbook workbook = writeExcel.createSheet(supermarkets);
workbook.write(os);
IOUtils.closeQuietly(os);
}
4) My WriteExcel Class that build the xlsx file:
private static String[] columns = {"Code", "Name", "Type"};
public Workbook createSheet(List<Supermarket> supermarkets) throws IOException {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("file");
[....]
// Row for Header
Row headerRow = sheet.createRow(0);
// Header
for (int col = 0; col < columns.length; col++) {
Cell cell = headerRow.createCell(col);
cell.setCellValue(columns[col]);
cell.setCellStyle(headerCellStyle);
}
//Content
int rowIdx = 1;
for (Supermarket supermarket : supermarkets) {
Row row = sheet.createRow(rowIdx++);
row.createCell(0).setCellValue(supermarket.getCode());
row.createCell(1).setCellValue(supermarket.getName());
row.createCell(2).setCellValue(supermarket.getType());
}
return workbook;
}
So, this all above is just for the first GET requisition. I make another one and the method below holds the second requisition. I just verify the token that the frontend returns for me and them, based on the validation, i allow the download of the file that i created on the previous step:
public void export(#PathVariable(value = "frontendToken") String frontendToken, HttpServletResponse response) throws IOException {
if (StringUtils.isNotBlank(frontendToken)) {
String tmpdir = System.getProperty("java.io.tmpdir");
File folder = new File(tmpdir);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
boolean fileIsValid = tokenGenerator.validateToken(frontendToken, listOfFiles[i]);
if (fileIsValid) {
InputStream input = new FileInputStream(listOfFiles[i]);
OutputStream output = response.getOutputStream();
int data = input.read();
while (data != -1) {
output.write(data);
data = input.read();
}
input.close();
output.flush();
output.close();
String mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
response.setContentType(mimeType);
listOfFiles[i].delete();
}
}
}
}
}
And that's all that i'm doing. Can't find what's wrong or what i'm missing. When i press F12 on my navigator to see the response of the request, shows for me something encoded, like:
PK#SM_rels/.rels­’ÁjÃ0†_ÅèÞ8í`ŒQ·—2èmŒî4[ILbËØÚ–½ýÌ.[Kì($}ÿÒv?‡I½Q.ž£uÓ‚¢hÙùØx>=¬î#ÁèpâH"Ã~·}¢
Any suspicions of what can be?

guys!
The problem was: my binary data was being converted for string by javascript and this was breaking my excel file. i solved my problem converting my binary data on backend to text and then on frontend i make the inverse. The following links helped me:
java convert inputStream to base64 string
Creating a Blob from a base64 string in JavaScript
Thank you for everyone that tried to help. I hope my question can help others

Related

Capture audio with naudio and play with javascript

I have a client with written c# and a server with written java. I capture audio and send with socket to the server and server send with web socket to the browser and want to play with browser. But when i try browser says Uncaught (in promise) DOMException: Failed to load because no supported source was found.
Could you help me?
private static void Recordwav()
{
waveInEvent = new WaveInEvent();
int devicenum = 0;
for (int i = 0; i < WaveIn.DeviceCount; i++)
{
if (WaveIn.GetCapabilities(i).ProductName.Contains("icrophone"))
devicenum = i;
}
waveInEvent.DeviceNumber = devicenum;
waveInEvent.WaveFormat = new WaveFormat(44100, WaveIn.GetCapabilities(devicenum).Channels);
waveInEvent.DataAvailable += new EventHandler<WaveInEventArgs>(VoiceDataAvailable);
waveInEvent.StartRecording();
}
private static void VoiceDataAvailable(object sender, WaveInEventArgs e)
{
JObject jObject = new JObject();
jObject["voice"] = Convert.ToBase64String(e.Buffer);
byte[] messageByte = Encoding.ASCII.GetBytes(jObject.ToString().Replace("\r\n", "") + "\n");
socket.Send(messageByte);
}
$scope.socket.onmessage = function (response)
{
var data = JSON.parse(response.data);
if(data.id == $scope.id) {
if(data.voice) {
var voice = data.voice;
var sound = new Audio("data:audio/wav;base64," + voice);
sound.play();
}
}
};
you're just sending raw samples, not a properly formatted WAV file. You'd need to use WaveFileWriter to write to a MemoryStream (wrapped in an IgnoreDisposeStream) dispose the WaveFileWriter and then access the MemoryStream underlying byte array. Also you're not taking into account BytesRecorded.
Even if you get this working, I suspect you'll get very choppy audio, as each WAV file will be a few hundred ms, and they won't necessarily play perfectly one after the other.

How can show document file in iframe when i get the file name from database?

How can show document file in iframe when i get the file name from database?My database table name is File and my viewmodel is MyFileModel.
public ActionResult Create(HttpPostedFileBase file)
{
try
{
if (ModelState.IsValid)
{
db.Files.Add(new File()
{
FileName = Path.GetFileName(file.FileName)
});
db.SaveChanges();
}
}
catch (Exception)
{
var error = "Sorry not save";
}
return Content("");
}
public FileStreamResult GetPDF()
{
var file = db.Files.Single(s => s.Id == 1);
FileStream fs = new FileStream(Server.MapPath(file.FileName), FileMode.Open, FileAccess.Read);
return File(fs, "application/pdf");
//return View(Server.MapPath("~/File/SegmentAdd.txt"));
//return File(fs,"text/plain");
}
<div id="frame">
<iframe src="#Url.Action("GetPDF","Home")" width="900px" height="500px"></iframe>
</div>
`
The answer which I am posting is all on an assumption, I do not have clear picture of your solution.
If you are not saving a physical file try to save it in a folder and then save the name in the DB OR try to save the entire path in the DB.
Method 1 :
If you are saving the file in a folder say File best way is to add a key in the web.config(.config file which is at the root) as follows
<add key="FilePath" value= "~/File/"/>
and then modify your C# code as follows
public FileStreamResult GetPDF()
{
var file = db.Files.Single(s => s.Id == 1);
string fileName = file.FileName;
string filePath = ConfigurationManager.AppSettings["FilePath"] + fileName;
FileStream fs = new FileStream(Server.MapPath(filePath), FileMode.Open, FileAccess.Read);
return File(fs,"text/plain"); // "text/plain" if your file content-type is text file
//return View(Server.MapPath("~/File/SegmentAdd.txt"));
//return File(fs,"text/plain");
}
Method 2 :
If you are saving the entire path then it makes coding much more simpler and you need not change the code you have written, just go ahead with the same.
Hope this would help you.
I think the way the pdf will open is dependent on the browser that the user uses.
You probably need something like: https://pdfobject.com/.
Good luck!

base64 to image filename [duplicate]

Here is my code:
protected void SaveMyImage_Click(object sender, EventArgs e)
{
string imageUrl = Hidden1.Value;
string saveLocation = Server.MapPath("~/PictureUploads/whatever2.png") ;
HttpWebRequest imageRequest = (HttpWebRequest)WebRequest.Create(imageUrl);
WebResponse imageResponse = imageRequest.GetResponse();
Stream responseStream = imageResponse.GetResponseStream();
using (BinaryReader br = new BinaryReader(responseStream))
{
imageBytes = br.ReadBytes(500000);
br.Close();
}
responseStream.Close();
imageResponse.Close();
FileStream fs = new FileStream(saveLocation, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
try
{
bw.Write(imageBytes);
}
finally
{
fs.Close();
bw.Close();
}
}
}
The top imageUrl declartion is taking in a Base64 image string, and I want to convert it into an image. I think my set of code only works for images like "www.mysite.com/test.jpg" not for a Base64 string. Anybody have some suggestions? Thanks!
Here is an example, you can modify the method to accept a string parameter. Then just save the image object with image.Save(...).
public Image LoadImage()
{
//data:image/gif;base64,
//this image is a single pixel (black)
byte[] bytes = Convert.FromBase64String("R0lGODlhAQABAIAAAAAAAAAAACH5BAAAAAAALAAAAAABAAEAAAICTAEAOw==");
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
return image;
}
It is possible to get an exception A generic error occurred in GDI+. when the bytes represent a bitmap. If this is happening save the image before disposing the memory stream (while still inside the using statement).
You can save Base64 directly into file:
string filePath = "MyImage.jpg";
File.WriteAllBytes(filePath, Convert.FromBase64String(base64imageString));
Here is what I ended up going with.
private void SaveByteArrayAsImage(string fullOutputPath, string base64String)
{
byte[] bytes = Convert.FromBase64String(base64String);
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
image.Save(fullOutputPath, System.Drawing.Imaging.ImageFormat.Png);
}
I would suggest via Bitmap:
public void SaveImage(string base64)
{
using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(base64)))
{
using (Bitmap bm2 = new Bitmap(ms))
{
bm2.Save("SavingPath" + "ImageName.jpg");
}
}
}
Here is working code for converting an image from a base64 string to an Image object and storing it in a folder with unique file name:
public void SaveImage()
{
string strm = "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
//this is a simple white background image
var myfilename= string.Format(#"{0}", Guid.NewGuid());
//Generate unique filename
string filepath= "~/UserImages/" + myfilename+ ".jpeg";
var bytess = Convert.FromBase64String(strm);
using (var imageFile = new FileStream(filepath, FileMode.Create))
{
imageFile.Write(bytess, 0, bytess.Length);
imageFile.Flush();
}
}
In my case it works only with two line of code. Test the below C# code:
String dirPath = "C:\myfolder\";
String imgName = "my_mage_name.bmp";
byte[] imgByteArray = Convert.FromBase64String("your_base64_string");
File.WriteAllBytes(dirPath + imgName, imgByteArray);
That's it. Kindly up vote if you really find this solution works for you. Thanks in advance.
In a similar scenario what worked for me was the following:
byte[] bytes = Convert.FromBase64String(Base64String);
ImageTagId.ImageUrl = "data:image/jpeg;base64," + Convert.ToBase64String(bytes);
ImageTagId is the ID of the ASP image tag.
If you have a string of binary data which is Base64 encoded, you should be able to do the following:
byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
You should be able to write the resulting array to a file.
public bool SaveBase64(string Dir, string FileName, string FileType, string Base64ImageString)
{
try
{
string folder = System.Web.HttpContext.Current.Server.MapPath("~/") + Dir;
if (!Directory.Exists(folder))
{
Directory.CreateDirectory(folder);
}
string filePath = folder + "/" + FileName + "." + FileType;
File.WriteAllBytes(filePath, Convert.FromBase64String(Base64ImageString));
return true;
}
catch
{
return false;
}
}
Using MemoryStream is not a good idea and violates a specification in MSDN for Image.FromStream(), where it says
You must keep the stream open for the lifetime of the Image.
A better solution is using ImageConverter, e.g:
public Image ConvertBase64ToImage(string base64)
=> (Bitmap)new ImageConverter().ConvertFrom(Convert.FromBase64String(base64));
In NetCore 6.0, you can use HttpClient and the async methods in the new File class.
The implementation is very simple:
static async Task DownloadFile(string imageUrl, string pathToSave)
{
var content = await GetUrlContent(url);
if (content != null)
{
await File.WriteAllBytesAsync(pathToSave, content);
}
}
static async Task<byte[]?> GetUrlContent(string url)
{
using (var client = new HttpClient())
using (var result = await client.GetAsync(url))
return result.IsSuccessStatusCode ? await result.Content.ReadAsByteArrayAsync():null;
}
Usage:
await DownloadFile("https://example.com/image.jpg", #"c:\temp\image.jpg");

Saving image to the user’s contacts with Cordova Contacts plugin

I seem to be having trouble saving an image to the user’s contacts with the Cordova Contacts plugin on Android. Here is my code:
var contact = navigator.contacts.create();
// data.photo is a valid base64-encoded string.
contact.photos[0] = {
"type": "base64",
"value": data.photo
};
contact.save(function() {
alert(“Contact saved.”);
}
This works perfectly on iOS but I can’t save an image on Android no matter what I try. The data.photo value is a valid base64-encoded string that WILL show up as an image when pasted into a URL bar. Any advice?
This problem is about that unsupported to save type base64.
You can found out that there is no type of base64 in ContactAccessorSdk5.java, which location is in Project folder in 'Platform/android/build/src/org/apache/cordova/contacts/ContactAccessorSdk5.java'
base64 of image data format start with 'data:'. so, you can modify getPathFromUri(String path) in the 'ContactAccessorSdk5.java' file for saving image data base64.
you can refer in 'https://groups.google.com/forum/#!msg/phonegap/jTMu9Azjaa8/ywQMMEcoS1YJ'
or my GitHub below.
https://github.com/CordovaExam/Contacts
You can get it if you get there, there is more detail information.
private InputStream getPathFromUri(String path) throws IOException {
if (path.startsWith("data:")) { // data:image/png;base64,[ENCODED_IMAGE]
String dataInfos = path.substring(0, path.indexOf(',')); // data:image/png;base64
dataInfos = dataInfos.substring(dataInfos.indexOf(':') + 1); // image/png;base64
String baseEncoding = dataInfos.substring(dataInfos.indexOf(';') + 1); // base64
if("base64".equalsIgnoreCase(baseEncoding)) {
String img = path.substring(path.indexOf(',') + 1); // [ENCODED_IMAGE]
byte[] encodedData = img.getBytes();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(encodedData, 0, encodedData.length);
Base64InputStream base64InputStream = new Base64InputStream(byteArrayInputStream, Base64.DEFAULT);
return base64InputStream;
} else {
Log.w(LOG_TAG, "Could not decode image. The found base encoding is " + baseEncoding);
}
}
if (path.startsWith("content:")) {
Uri uri = Uri.parse(path);
return mApp.getActivity().getContentResolver().openInputStream(uri);
}
if (path.startsWith("http:") || path.startsWith("https:") || path.startsWith("file:")) {
URL url = new URL(path);
return url.openStream();
}
else {
return new FileInputStream(path);
}
}

How to read excel File from ASHX page?

Hi i have uploaded file to one amazon s3 server,how can i read excel file and want to send excel data to database.
my code is
<script type="text/javascript">
var obj = null;
$(function () {
$('#fileupload').fileupload({
replaceFileInput: false,
formData: function (form) {
return [{ name: "name1", value: "value1" }, { name: "name2", value: "value2"}];
$('#btnGo').click(function () {
obj.submit();
});
});
</script>
And my ashx page, where i need to read excel data
public class AjaxFileHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
var file = context.Request.Files[0];
string fileName=fileName = Guid.NewGuid().ToString() + file.FileName;
Stream streamContentFile = context.Request.Files[0].InputStream;
var iFileSize = context.Request.Files[0].ContentLength;
byte[] data = new byte[iFileSize];
int bytes_read = 0;
while (bytes_read < iFileSize)
{
int bytes_read_this_iteration = streamContentFile.Read(data, bytes_read, iFileSize - bytes_read);
streamContentFile.Close();
streamContentFile.Dispose();
CommonBLL.UploadTemporaryFilesToS3Bucket(fileName, data);
//Here i need to read excel code can you provide how to do that pleas
}
I would use open source libraries for excel, EPPlus (xslx) or NPOI (xls). They are very easy to use, and I am using EPPlus for numerous excel imports / exports and it's working great. These libraries have no external dependancies, and you can use it on server side.
you need two things:
a Driver that allows code to read Excel content
access to this file
a query over excel data
In this sample:
I use ACE (Microsoft Access Database Engine) driver, that must be installed on the server
the file is in App_Data folder (in your case the file should be rached CommonBLL library, i suppose)
the query is an UPDATE query; you can replace with a SELECT or INSERT query, using common DB SNippets.
string fileName= Server.MapPath( "~/App_Data/MyFile.xls");
string sheetName= "Sheet1";
string connString = string.Format(
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR=No'"
, fileName);
string command = string.Format("UPDATE [{0}${1}:{1}] SET F1='{2}'", sheetName,cellName, cellValue);
using (OleDbConnection oledbConn = new OleDbConnection(connString))
{
oledbConn.Open();
using (OleDbCommand cmd = new OleDbCommand(command, oledbConn))
cmd.ExecuteNonQuery();
oledbConn.Close();
}

Categories