Get contents of a zip file - javascript

This URL below points to a zip file which contains a file called bundlesizes.json. I am trying to read the contents of that json file within my React application (no node server/backend involved)
https://dev.azure.com/uifabric/cd9e4e13-b8db-429a-9c21-499bf1c98639/_apis/build/builds/8838/artifacts?artifactName=drop&api-version=4.1&%24format=zip
I was able to get the contents of the zip file by doing the following
const url =
'https://dev.azure.com/uifabric/cd9e4e13-b8db-429a-9c21-499bf1c98639/_apis/build/builds/8838/artifacts?artifactName=drop&api-version=4.1&%24format=zip';
const response = await Axios({
url,
method: 'GET',
responseType: 'stream'
});
console.log(response.data);
This emits the zip file (non-ascii characters). However, I am looking to read the contents of the bundlesizes.json file within it.
For that I looked up jszip and tried the following,
var zip = new JSZip();
zip.createReader(
new zip.BlobReader(response.data),
function(reader: any) {
// get all entries from the zip
reader.getEntries(function(entries: any) {
if (entries.length) {
// get first entry content as text
entries[0].getData(
new zip.TextWriter(),
function(text: any) {
// text contains the entry data as a String
console.log(text);
// close the zip reader
reader.close(function() {
// onclose callback
});
},
function(current: any, total: any) {
// onprogress callback
console.log(current);
console.log(total);
}
);
}
});
},
function(error: any) {
// onerror callback
console.log(error);
}
);
However, this does not work for me, and errors out.
This is the error I receive
How can I read the contents of the file within the zip within my React application by using Javascript/Typescript?

Related

Downloaded xlsx file with fileSaver is invalid when opened

I have written function where I want to download an xlsx file via a service. Download also works so far. But when I open the file I get the error message file extension or file format is invalid. How can I solve the problem?
Code:
// Service
getDownloadPlan(): Observable<any> {
const url = `/download-plan?sales-plan=0&personnel-plan=0&investment-plan=0&loan-plan=0&material-cost-plan=0`;
return this.http.get(`${environment.baseUrl}` + url, { responseType: 'blob'});
}
// TS
downloadPlanBwa() {
this.planBwaService.getDownloadPlan().subscribe(response => {
const downloadFile: any = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
fileSaver.saveAs(downloadFile, 'Plan');
}, error => console.log('ERROR'),
() => console.log('SUCCESSFUL')
);
}
If i use the MIME-Type application/vnd.ms-excel;charset=utf-8 this is for the xls-format then it works.
What do I need to change in my code to successfully open xlsx files?

how to send multiple files into fire base storage and save their URL in real time database in one record

i want to send multiple file to Fire-base storage and meantime it has to save real-time database as a one record using java-script
ex:
file1 : urlonfirstfile
file2 : urlonsecondfile
for (var i = 0; i < file.length; i++) {
var task = ref.child(file.name).put(file, metadata);
task
.then(snapshot => snapshot.ref.getDownloadURL())
.then((url) => {
console.log(url);
userDetails.push({
email : email,
title1: tit,
detail1: dit,
file:file[i].name
});
});
}
Your question is kinda vague on what information you want to store. So I've made some assumptions to come up with the below code:
The files are to be uploaded to an area of Firebase Storage specific to the logged in user. (e.g. "userFiles/CURRENT_USER/...")
The information about the uploaded files are kept under the user's own data. (e.g. "users/CURRENT_USER/uploads/..."
The title and detail properties change for each file. Where these properties come from is unclear, so I'm just going to assume they are passed in through the object metadata.
The code below should be enough to get you started on figuring out your own solution.
// the array of File objects to upload
const fileObjArray = [ ... ]
// the metadata to store with each file
const metadata = { ... }
// the current user's ID
const currentUserId = firebase.auth().currentUser.uid;
// Where to save information about the uploads
const databaseRef = firebase.database().ref("user").child(currentUserId).child('uploads');
// Create an ID for this set of uploaded files
const uploadId = storageRef.push().key;
// Save files to storage in a subfolder of the user's files corresponding to the uploadId
const storageRef = firebase.storage().ref("userFiles").child(currentUserId).child(uploadId);
// Upload each file in fileObjArray, then fetch their download URLs and then return an object containing information about the uploaded file
var uploadPromiseArray = fileObjArray.map((fileObj) => {
var uploadTask = storageRef.child(fileObj.name).put(fileObj, metadata)
return uploadTask.then(uploadSnapshot => {
// file uploaded successfully. Fetch url for the file and return it along with the UploadTaskSnapshot
return uploadSnapshot.ref.getDownloadURL().then((url) => {
return {
downloadUrl: url,
snapshot: uploadSnapshot
};
});
});
});
// uploadPromiseArray is an array of Promises that resolve as objects with the properties "downloadUrl" and "snapshot"
Promise.all(uploadPromiseArray)
.then((uploadResultArray) => {
var batchUploadData = {
timestamp: firebase.database.ServerValue.TIMESTAMP, // use the server's time
files: [],
... // other upload metadata such as reason, expiry, permissions, etc.
}
batchUploadData.files = uploadResultArray.map((uploadResult) => {
// rearrange the file's snapshot data and downloadUrl for storing in the database
return {
file: uploadResult.snapshot.name,
url: uploadResult.url,
title: uploadResult.snapshot.metadata.customMetadata.title,
detail: uploadResult.snapshot.metadata.customMetadata.detail
};
});
// commit the data about this upload to the database.
return databaseRef.child(uploadId).set(batchUploadData);
})
.then((dataSnapshot) => {
// the upload completed and information about the upload was saved to the database successfully
// TODO: do something
}, (err) => {
// some error occured
// - a file upload failed/was cancelled
// - the database write failed
// - permission error from Storage or Realtime Database
// TODO: handle error
});
// Warning: this line will be reached before the above code has finished executing
This is what it looks like on the database:
"users": {
"someUserId-78sda9823": {
"email": "example#example.com",
"name": "mr-example",
"username": "mrexemplary",
"uploads": {
"niase89f73oui2kqwnas98azsa": {
"timestamp": 1554890267823,
"files": {
"1": {
"file": "somefile.pdf",
"url": "https://firebasestorage.googleapis.com/v0/b/bucket/o/userFiles%2FsomeUserId-78sda9823%2Fsomefile.pdf",
"title": "Some File",
"detail": "Contains a report about some stuff"
},
"2": {
"file": "screenshot.png",
"url": "https://firebasestorage.googleapis.com/v0/b/bucket/o/userFiles%2FsomeUserId-78sda9823%2Fscreenshot.png",
"title": "Screenshot of problem",
"detail": "Contains an image that shows some stuff"
},
...
}
},
...
},
...
},
...
}
Note 1: This code is not yet complete. It is missing error handling for things like permission errors and incomplete file uploads. This is a problem for you to solve.
Note 2: Regarding incomplete file uploads, if any file fails to upload or get it's download URL successfully, the database will not be written to. One possible way to aid with this is to add a catch to uploadTask that returns null on error and then in the uploadResultArray.map(...) step skip any uploadResult variables that are null or write to the database that it failed for that particular file.
Note 3: Because Firebase Storage and the Realtime Database both use snapshots, try to keep them called uploadSnapshot/fileSnapshot and dataSnapshot respectively when using both in your code to minimise confusion. Similarly, name your references somethingStorageRef/somethingSRef and somethingDatabaseRef/somethingDBRef.

How to upload a file along with text using fetch in react native?

I'm trying to upload a file to the server using react-native-document-picker. The problem I'm facing is I don't know how to upload the file along with a text.In my app there is a portion for file upload also there is an area for writing some text.Then it will get uploaded to the server.So I've done the following.But I'm getting this error after submitting to server
unhandled promise rejection unsupported BodyInit type
updated portion of code
filepick = () => {
DocumentPicker.show({
filetype: [DocumentPickerUtil.images()],
}, (error, res) => {
if (error == null) {
console.log(
res.uri,
res.type, // mime type
res.fileName,
res.fileSize
);
this.setState({
img_uri: res.uri,
img_type: res.type,
img_name: res.fileName
})
} else {
Alert.alert('Message', 'File uploaded failed');
}
});
};
onPressSubmit() {
const data = new FormData();
data.append('file', { uri: this.state.img_uri, type:
this.state.img_type, name: this.state.img_name })
data.append('comment', { text: this.state.text });
AsyncStorage.getItem("userdetail").then(value => {
fetch(GLOBAL.ASSN_URL +`${this.props.id}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
'Authorization': value
},
body: data
}).then((response) => {
return response.text()
}).then((responseJson) => {
var result = responseJson;
console.log(result);
});
})
}
The function filepick() is called after choosing a file from your device.Please help me to find a solution.How do I upload this to server also how to send text without stringifying it?
body: ({
file: this.state.file,
comment: this.state.text
})
Why are you wrapping body in brackets? Removing them might fix it.
Also see this, https://github.com/facebook/react-native/issues/6025 you might want to stringify the body object, since your content type is not application/json
body: JSON.stringify({
file: this.state.file,
comment: this.state.text
})
Edit
From comments we now know the following
1) You are uploading a file separately.
2) The upload response contains information about the file
3) You are saving the entity in separate server call
4) You need to save file with that entity
The solution below assumes that you have full control over server and you are also handling the file uploading endpoint. Here is the solution
You basically do not need to upload the whole file again with your entity since it is already uploaded on server, all you need to do is to save the reference of the file with entity. Their are two ways to save the reference
1) Just save either the fileName or fileUrl in your entity table and then store the name or url with entity so it will look like this
{
id: 1,
name: 'Cat',
picture: // url or name of picture
}
2) Save the uploaded file in different table, then save the id of the file with your entity, and when you fetch entities get the related file. However if the relationship between entity and file is one to many as in one entity can have many files then you will first need to save the entity and then upload the files with reference of entity. This way your entity will look like this
{
id: 1,
name: 'Cat',
pictures: [{fileName: 'cat1'}, {fileName: 'cat2'}]
}

Google drive API - ulpoad an audio blob converted in base64 string- drive.files.create method - File id not found

I'm trying to sent an audio blob on some Google drive folder. To succeed I translate blob in file before sending it.
I received since the starting an error :
Error: File not found.
code: 404, errors: [ { domain: 'global',
reason: 'notFound',
message: 'File not found: 1aazd544z3FOCAsdOA5E7XcOaS3297sU.',
locationType: 'parameter',
location: 'fileId' } ] }
progressive edit : So far I have converted my audio blob in base64 string in order to ease the processing of my blob.
But, I fail always to write a file with my base 64 audio blob :
Here my driveApi.js :
// request data from req.body
var data = req.body.data ; // data variable is presented in form of base64 string
var name = req.body.word ;
(...)
// WRITE FILE AND STORE IT IN BODY HEADER PROPERTY
body: fs.writeFile((name + ".mp3"), data.substr(data.indexOf(',')+1), {encoding: 'base64'}, function(err) {
console.log('File created')
})
Three steps: create a temporary file with your base64 data out of the drive.files.create function, then give this file a specific name -e.g. tempFile, also you can customize this name with a time value. After that, pass this file on a "fs.createReadStream" method to upload it on Google drive.
Some hints:
Firstly - use path.join(__dirname, name + "-" + Date.now() +".ext" ) to create to file name
Secondly - make this process asynchronously to avoid data flow conflict (trying to create file before file is created), so call the drive.files.create after having setting a fs.writeFile function.
Thirdly - Destroy the tempFile after the operation has been done. It allows you to automatize the process.
I let you dive in the methods you need. But basically fs should do the job.
Again, be careful on the data flow and use callback to control it. Your code can crash just because the function gone up in a no-operational way.
Some links :
https://nodejs.org/api/path.html
https://nodejs.org/api/fs.html#fs_fs_writefile_file_data_options_callback
here an instance :
// datavalue = some time value
fs.writeFile(
path.join(__dirname, name + "-" + datevalues +".mp3" ),
data.substr(data.indexOf(',')+1),
{encoding: 'base64'},
// callback
function(err) {
if(err){ console.log("error writting file : " + err)}
console.log('File created')
console.log("WRITTING") // control data flow
fileCreate(name)
})
function fileCreate (name){
// upload file in specific folder
var folderId = "someID";
var fileMetadata = {
'name': name + ".mp3" ,
parents: [folderId]
}; console.log("MEDIA") // control data flow
var media = {
mimeType: 'audio/mp3',
body: fs.createReadStream(path.join(__dirname, name + "-" + datevalues +".mp3" ))
};
drive.files.create({
auth: jwToken,
resource: fileMetadata,
media: media,
fields: 'id'
}, function (err, file) {
if (err) {
// Handle error
console.error(err);
} else {
console.log('File Id: ', file.data.id);
}
// make a callback to a deleteFile() function // I let you search for it
});
}
How about this modification? I'm not sure the condition of blob from reactApp.js. So could you please try to use this modification? In this modification, file or blob from reactApp.js are used.
Modified script :
var stream = require('stream'); // Added
module.exports.uploadFile = function(req){
var file ;
console.log("driveApi upload reached")
function blobToFile(req){
file = req.body.blob
//A Blob() is almost a File() - it's just missing the two properties below which we will add
file.lastModifiedDate = new Date();
file.name = req.body.word;
return file;
}
var bufStream = new stream.PassThrough(); // Added
bufStream.end(file); // Or bufStream.end(### blob from reactApp.js ###) Added
console.log(typeof 42);
// upload file in specific folder
var folderId = "1aa1DD993FOCADXUDNJKLfzfXcOaS3297sU";
var fileMetadata = {
"name": req.body.word,
parents: [folderId]
}
var media = {
mimeType: "audio/mp3",
body: bufStream // Modified
}
drive.files.create({
auth: jwToken,
resource: fileMetadata,
media: media,
fields: "id"
}, function (err, file) {
if (err) {
// Handle error
console.error(err);
} else {
console.log("File Id: ", file.id);
}
console.log("driveApi upload accomplished")
});
}
If this didn't work, I'm sorry.

File upload blocking with bigger files

Intro
What I'm trying to achieve is a simple file upload with a progress indication with redux-saga and react). I'm having problems getting this indication because the file upload seems the be blocking - which it shouldn't be.
Expected behaviour
before the file upload starts a re render is triggered and the spinner is shown and the window is not blocked.
Current behaviour
What I have at the moment is a component with a table that show a file per row. A optimistic row gets added with a spinner as the content when the users uploads a file. As soon as the file is uploaded the optimistic row will be replaced by a real row with the file's name etc. When I'm uploading a file around 50MB the window gets blocked and shortly before the file is uploaded (around 0.5s before) the spinner appears and then the file is already uploaded and the spinner disappears again.
side notes
If you replace the file upload with new Promise(res => setTimeout(res, 5000)) it all works fine => it seems like there is a problem with the xhr / fetch.
I've implemented the same using XHR, promises and an onProgress callback to make sure the problem is not fetch.
the implementation looks very close to: https://gist.github.com/robinfehr/2f4018259bf026a468cc31100fed5c9f
Also with this implementation I've experienced the same issue - blocking until almost the end of the upload.
If I put log statements into the render function of the component to see if it's getting re rendered before the file is uploaded, I see (as soon as the block stops and the file is uploaded) that the log statements in the render function are actually correctly triggered with a timestamp before the file upload was done.
In this implementation I'm using the same reducer: optimistic event as well as the real event that reverts the optimistic event, they go trough the same reducer (named fileReducer here).
using a second reducer and concatination instead of the optimistic revert logic helps to displaying the spinner earlier but does not help with the blocking. It therefore seems like the middleware also gets blocked by the blocking call.
saga: (postData uses fetch)
function* createDocument(partnerId, { payload, meta }) {
const siteId = getSiteIdFromRoute();
const {
mediaGroupId,
customArticleId,
logicalComponentId,
type,
name,
documentSrc,
meta: metaFromFrontEnd
} = payload;
const commonEventId = uuid();
const hans = {
optimistic: true
};
const payloadBasic = {
id: commonEventId,
version: 0,
aggregate: {
id: uuid(),
name: 'document'
},
context: {
name: 'contentManagement'
},
payload: {
name,
type,
links: {
partnerId,
siteId,
logicalComponentId,
customArticleId,
mediaGroupId
}
}
};
// creates the optimistic (fake) row with a spinner in the file list component - action marked as optimistic which will be reverted.
yield put(actions.denormalizeEvent({
...payloadBasic,
name: 'documentCreated',
optimistic: true,
payload: {
...payloadBasic.payload,
uploading: true
}
}));
yield fork(executeDocumentUpload, type, siteId, partnerId, documentSrc, payloadBasic);
}
function* executeDocumentUpload(type, siteId, partnerId, documentSrc, payloadBasic) {
const req = yield call(uploadDocument, type, siteId, partnerId, documentSrc);
const body = yield req.json();
const { meta: metaFromFileUpload, id } = body.response;
// removes the optimistic (fake) row from the file list component and and adds the real row with more file information (optimistic event gets reverted in middleware)
yield put(actions.sendCommandSuccess({
...payloadBasic,
name: 'createDocument',
payload: {
...payloadBasic.payload,
meta: metaFromFileUpload
}
}));
}
function uploadDocument(type, siteId, partnerId, documentSrc) {
let url;
if (type === 'site' || type === 'mediaGroup' || type === 'logicalComponent') {
url = `/file/site/${siteId}/document`;
} else if (type === 'customArticle') {
url = `/file/partner/${partnerId}/document`;
}
return postData(url, documentSrc);
}
The problem was that I did send the file as a base64 encode string and set up the request with the wrong content-type.
'Content-Type': 'text/plain;charset=UTF-8'
putting the file into a FormData object and send the request without the mentioned content-type lead to a non-blocking request.

Categories

Resources