Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix file upload #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 113 additions & 77 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,165 +2,203 @@
const wfs = require("wfs-local");
const root = process.argv[3];
const drive = new wfs.LocalFiles(root, null, {
verbose: true
verbose: true,
});


// init REST API
const fs = require("fs")
const fs = require("fs");
const cors = require("cors");
const path = require("path");
const Busboy = require("busboy");
const express = require("express");
const bodyParser = require("body-parser");
const { Readable } = require('stream')
const { Readable, PassThrough } = require("stream");

const app = express();
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.urlencoded({ extended: true }));

app.get("/info", async (req, res, next)=>{
app.get("/info", async (req, res, next) => {
const id = req.query.id;
const { free, used } = await drive.stats(id);
res.send({
stats:{ free, used, total: free+used },
features:{ preview:{}, meta:{} }
stats: { free, used, total: free + used },
features: { preview: {}, meta: {} },
});
});

app.get("/files", async (req, res, next)=>{
app.get("/files", async (req, res, next) => {
const id = req.query.id;
const search = req.query.search;

const config = {
exclude: a => a.indexOf(".") === 0
exclude: a => a.indexOf(".") === 0,
};
if (search){
if (search) {
config.subFolders = true;
config.include = a => a.indexOf(search) !== -1;
}

res.send( await drive.list(id, config));
res.send(await drive.list(id, config));
});

app.get("/folders", async (req, res, next)=>{
res.send( await drive.list("/", {
skipFiles: true,
subFolders: true,
nested: true,
exclude: a => a.indexOf(".") === 0
}));
app.get("/folders", async (req, res, next) => {
res.send(
await drive.list("/", {
skipFiles: true,
subFolders: true,
nested: true,
exclude: a => a.indexOf(".") === 0,
})
);
});

app.get("/icons/:size/:type/:name", async (req, res, next)=>{
const url = await getIconURL(req.params.size, req.params.type, req.params.name, "");
res.sendFile(path.join(__dirname, url))
app.get("/icons/:size/:type/:name", async (req, res, next) => {
const url = await getIconURL(
req.params.size,
req.params.type,
req.params.name,
""
);
res.sendFile(path.join(__dirname, url));
});

app.get("/icons/:skin/:size/:type/:name", async (req, res, next)=>{
const url = await getIconURL(req.params.size, req.params.type, req.params.name, req.params.skin);
res.sendFile(path.join(__dirname, url))
app.get("/icons/:skin/:size/:type/:name", async (req, res, next) => {
const url = await getIconURL(
req.params.size,
req.params.type,
req.params.name,
req.params.skin
);
res.sendFile(path.join(__dirname, url));
});

app.post("/copy", async (req, res, next)=>{
app.post("/copy", async (req, res, next) => {
const source = req.body.id;
const target = req.body.to;

res.send(await drive.info(await drive.copy(source, target, "", { preventNameCollision: true })));
res.send(
await drive.info(
await drive.copy(source, target, "", { preventNameCollision: true })
)
);
});

app.post("/move", async (req, res, next)=>{
app.post("/move", async (req, res, next) => {
const source = req.body.id;
const target = req.body.to;

res.send(await drive.info(await drive.move(source, target, "", { preventNameCollision: true })));
res.send(
await drive.info(
await drive.move(source, target, "", { preventNameCollision: true })
)
);
});

app.post("/rename", async (req, res, next)=>{
app.post("/rename", async (req, res, next) => {
const source = req.body.id;
const target = path.dirname(source);
const name = req.body.name;

res.send(await drive.info(await drive.move(source, target, name, { preventNameCollision: true })));
res.send(
await drive.info(
await drive.move(source, target, name, { preventNameCollision: true })
)
);
});

app.post("/upload", async (req, res, next)=>{
app.post("/upload", async (req, res, next) => {
const busboy = new Busboy({ headers: req.headers });


const files = {};
let path = [];

busboy.on("field", async (field, val) => {
if (field === "upload_fullpath") {
path = val.split("/").slice(0, -1);
}
});

busboy.on("file", async (field, file, name) => {
console.log(req.body, name)

busboy.on('field', async function(field, val) {
// support folder upload
let base = req.query.id;

const parts = val.split("/");
if (parts.length > 1){
for (let i = 0; i < parts.length - 1; ++i){
const p = parts[i];
const exists = await drive.exists(base + "/" + p);
if (!exists) {
base = await drive.make(base, p, true);
} else {
base = base + "/" + p;
}
}
}
console.log(req.body, name);
files[name] = new PassThrough({ highWaterMark: 32 * 1024 ** 2 }); // buffer threshold - 32MB
file.pipe(files[name]);
});

const target = await drive.make(base, name, false, { preventNameCollision: true });
res.send(await drive.info(await drive.write(target, file)));
});
busboy.on("finish", async () => {
let base = req.query.id;

// support folder upload
for (let i = 0; i < path.length; ++i) {
const p = path[i];
const newBase = base + "/" + p;
if (await drive.exists(newBase)) {
base = newBase;
} else {
base = await drive.make(base, p, true);
}
}

for (const name in files) {
const target = await drive.make(base, name, false, {
preventNameCollision: true,
});
res.send(await drive.info(await drive.write(target, files[name])));
}
});

req.pipe(busboy);
});


app.post("/makedir", async (req, res, next)=>{
const id = await drive.make(req.body.id, req.body.name, true, { preventNameCollision: true })
app.post("/makedir", async (req, res, next) => {
const id = await drive.make(req.body.id, req.body.name, true, {
preventNameCollision: true,
});
res.send(await drive.info(id));
});

app.post("/makefile", async (req, res, next)=>{
const id = await drive.make(req.body.id, req.body.name, false, { preventNameCollision: true })
app.post("/makefile", async (req, res, next) => {
const id = await drive.make(req.body.id, req.body.name, false, {
preventNameCollision: true,
});
res.send(await drive.info(id));
});

app.post("/delete", async (req, res, next)=>{
drive.remove(req.body.id)
res.send({})
});
app.post("/delete", async (req, res, next) => {
drive.remove(req.body.id);
res.send({});
});

app.post("/text", async (req, res, next)=>{
app.post("/text", async (req, res, next) => {
const name = req.body.id;
const content = req.body.content;
const id = await drive.write(name, Readable.from([content]));
res.send(await drive.info(id));
});

app.get("/text", async (req, res, next)=>{
app.get("/text", async (req, res, next) => {
const data = await drive.read(req.query.id);
data.pipe(res);
});

app.get("/direct", async (req, res, next) => {
const id = req.query.id;
const data = await drive.read(req.query.id);
const info = await drive.info(req.query.id);
const name = encodeURIComponent(info.value);

let disposition = "inline";
if (req.query.download){

if (req.query.download) {
disposition = "attachment";
}

res.writeHead(200, {
"Content-Disposition": `${disposition}; filename=${name}`
"Content-Disposition": `${disposition}; filename=${name}`,
});
data.pipe(res);
});

async function getIconURL(size, type, name, skin){
async function getIconURL(size, type, name, skin) {
size = size.replace(/[^A-Za-z0-9.]/g, "");
name = name.replace(/[^A-Za-z0-9.]/g, "");
type = type.replace(/[^A-Za-z0-9.]/g, "");
Expand All @@ -170,27 +208,25 @@ async function getIconURL(size, type, name, skin){
// get by name
`icons/default/${size}/${name}`,
// get by type with skin or not
( skin ? `icons/${skin}/${size}/types/${type}.svg` : null),
`icons/default/${size}/types/${type}.svg`
skin ? `icons/${skin}/${size}/types/${type}.svg` : null,
`icons/default/${size}/types/${type}.svg`,
].filter(a => a);

for (let i = 0; i < names.length-1; i++){
for (let i = 0; i < names.length - 1; i++) {
try {
await fs.promises.stat(names[i]);
return names[i];
} catch (e) { }
} catch (e) {}
}

return names[names.length-1];
return names[names.length - 1];
}



// load other assets
app.use(express.static("./"));

const port = "3200";
const host = "localhost";
app.listen(port, host, function () {
app.listen(port, host, function() {
console.log("Server is running on port " + port + "...");
});