fixes #96, downloads now work on safari and firefox

This commit is contained in:
Cassie Tarakajian 2016-11-02 14:08:53 -04:00
parent a06369ab06
commit 85b8f5b589
5 changed files with 64 additions and 54 deletions

View file

@ -42,7 +42,7 @@ function Nav(props) {
if (props.project.id) {
return (
<li className="nav__item">
<a className="nav__export" onClick={props.exportProjectAsZip}>
<a className="nav__export" onClick={() => props.exportProjectAsZip(props.project.id)}>
Download
</a>
</li>

View file

@ -1,9 +1,6 @@
import * as ActionTypes from '../../../constants';
import { browserHistory } from 'react-router';
import axios from 'axios';
import JSZip from 'jszip';
import JSZipUtils from 'jszip-utils';
import { saveAs } from 'file-saver';
import { showToast, setToastText } from './toast';
import { setUnsavedChanges, justOpenedProject, resetJustOpenedProject } from './ide';
@ -127,53 +124,9 @@ export function createProject() {
};
}
function buildZip(state) {
const zip = new JSZip();
const rootFile = state.files.find(file => file.name === 'root');
const numFiles = state.files.filter(file => file.fileType !== 'folder').length;
const files = state.files;
const projectName = state.project.name;
let numCompletedFiles = 0;
function addFileToZip(file, path) {
if (file.fileType === 'folder') {
const newPath = file.name === 'root' ? path : `${path}${file.name}/`;
file.children.forEach(fileId => {
const childFile = files.find(f => f.id === fileId);
(() => {
addFileToZip(childFile, newPath);
})();
});
} else {
if (file.url) {
JSZipUtils.getBinaryContent(file.url, (err, data) => {
zip.file(`${path}${file.name}`, data, { binary: true });
numCompletedFiles += 1;
if (numCompletedFiles === numFiles) {
zip.generateAsync({ type: 'blob' }).then((content) => {
saveAs(content, `${projectName}.zip`);
});
}
});
} else {
zip.file(`${path}${file.name}`, file.content);
numCompletedFiles += 1;
if (numCompletedFiles === numFiles) {
zip.generateAsync({ type: 'blob' }).then((content) => {
saveAs(content, `${projectName}.zip`);
});
}
}
}
}
addFileToZip(rootFile, '/');
}
export function exportProjectAsZip() {
return (dispatch, getState) => {
const state = getState();
buildZip(state);
};
export function exportProjectAsZip(projectId) {
const win = window.open(`${ROOT_URL}/projects/${projectId}/zip`, '_blank');
win.focus();
}
export function newProject() {

View file

@ -58,6 +58,7 @@
"node": ">=4"
},
"dependencies": {
"archiver": "^1.1.0",
"async": "^2.0.0",
"axios": "^0.12.0",
"babel-core": "^6.8.0",
@ -76,13 +77,10 @@
"eslint-loader": "^1.3.0",
"express": "^4.13.4",
"express-session": "^1.13.0",
"file-saver": "^1.3.2",
"file-type": "^3.8.0",
"htmlhint": "^0.9.13",
"js-beautify": "^1.6.4",
"jshint": "^2.9.2",
"jszip": "^3.0.0",
"jszip-utils": "0.0.2",
"lodash": "^4.16.4",
"loop-protect": "git+https://git@github.com/sagar-sm/loop-protect.git",
"moment": "^2.14.1",
@ -102,6 +100,7 @@
"redux": "^3.5.2",
"redux-form": "^5.3.3",
"redux-thunk": "^2.1.0",
"request": "^2.76.0",
"s3-policy": "^0.2.0",
"shortid": "^2.2.6",
"srcdoc-polyfill": "^0.2.0",

View file

@ -1,5 +1,8 @@
import Project from '../models/project';
import User from '../models/user';
import archiver from 'archiver';
import request from 'request';
export function createProject(req, res) {
let projectValues = {
@ -99,3 +102,56 @@ export function getProjectsForUser(req, res) {
return res.json([]);
}
}
function buildZip(project, req, res) {
const zip = archiver('zip');
const rootFile = project.files.find(file => file.name === 'root');
const numFiles = project.files.filter(file => file.fileType !== 'folder').length;
const files = project.files;
const projectName = project.name;
let numCompletedFiles = 0;
zip.on('error', function(err) {
res.status(500).send({error: err.message});
});
res.attachment(`${project.name}.zip`);
zip.pipe(res);
function addFileToZip(file, path) {
if (file.fileType === 'folder') {
const newPath = file.name === 'root' ? path : `${path}${file.name}/`;
file.children.forEach(fileId => {
const childFile = files.find(f => f.id === fileId);
(() => {
addFileToZip(childFile, newPath);
})();
});
} else {
if (file.url) {
request({ method: 'GET', url: file.url, encoding: null }, (err, response, body) => {
zip.append(body, { name: `${path}${file.name}` });
numCompletedFiles += 1;
if (numCompletedFiles === numFiles) {
zip.finalize();
}
});
} else {
zip.append(file.content, { name: `${path}${file.name}` });
numCompletedFiles += 1;
if (numCompletedFiles === numFiles) {
zip.finalize();
}
}
}
}
addFileToZip(rootFile, '/');
}
export function downloadProjectAsZip(req, res) {
Project.findById(req.params.project_id, (err, project) => {
//save project to some path
buildZip(project, req, res);
});
}

View file

@ -15,4 +15,6 @@ router.route('/projects').get(ProjectController.getProjects);
router.route('/:username/projects').get(ProjectController.getProjectsForUser);
router.route('/projects/:project_id/zip').get(ProjectController.downloadProjectAsZip);
export default router;