@@ -2,6 +2,7 @@ package controllers | |||
import ( | |||
"encoding/json" | |||
"mime/multipart" | |||
"github.com/casbin/casbase/object" | |||
) | |||
@@ -23,9 +24,21 @@ func (c *ApiController) UpdateFile() { | |||
func (c *ApiController) AddFile() { | |||
storeId := c.Input().Get("store") | |||
key := c.Input().Get("key") | |||
newFolder := c.Input().Get("newFolder") | |||
isLeaf := c.Input().Get("isLeaf") == "1" | |||
filename := c.Input().Get("filename") | |||
var file multipart.File | |||
if isLeaf { | |||
var err error | |||
file, _, err = c.GetFile("file") | |||
if err != nil { | |||
c.ResponseError(err.Error()) | |||
return | |||
} | |||
defer file.Close() | |||
} | |||
c.Data["json"] = object.AddFile(storeId, key, newFolder) | |||
c.Data["json"] = object.AddFile(storeId, key, isLeaf, filename, file) | |||
c.ServeJSON() | |||
} | |||
@@ -1,7 +1,10 @@ | |||
package object | |||
import ( | |||
"bytes" | |||
"fmt" | |||
"io" | |||
"mime/multipart" | |||
"github.com/casbin/casbase/storage" | |||
) | |||
@@ -10,14 +13,27 @@ func UpdateFile(storeId string, key string, file *File) bool { | |||
return true | |||
} | |||
func AddFile(storeId string, key string, newFolder string) bool { | |||
func AddFile(storeId string, key string, isLeaf bool, filename string, file multipart.File) bool { | |||
store := GetStore(storeId) | |||
if store == nil { | |||
return false | |||
} | |||
objectKey := fmt.Sprintf("%s/%s/_hidden.ini", key, newFolder) | |||
storage.PutObject(store.Bucket, objectKey) | |||
var objectKey string | |||
var fileBuffer *bytes.Buffer | |||
if isLeaf { | |||
objectKey = fmt.Sprintf("%s/%s", key, filename) | |||
fileBuffer = bytes.NewBuffer(nil) | |||
if _, err := io.Copy(fileBuffer, file); err != nil { | |||
panic(err) | |||
} | |||
} else { | |||
objectKey = fmt.Sprintf("%s/%s/_hidden.ini", key, filename) | |||
fileBuffer = bytes.NewBuffer(nil) | |||
} | |||
storage.PutObject(store.Bucket, objectKey, fileBuffer) | |||
return true | |||
} | |||
@@ -29,12 +45,11 @@ func DeleteFile(storeId string, key string, isLeaf bool) bool { | |||
if isLeaf { | |||
storage.DeleteObject(store.Bucket, key) | |||
return true | |||
} else { | |||
objects := storage.ListObjects(store.Bucket, key) | |||
for _, object := range objects { | |||
storage.DeleteObject(store.Bucket, object.Key) | |||
} | |||
return true | |||
} | |||
return true | |||
} |
@@ -48,11 +48,9 @@ func ListObjects(bucketName string, prefix string) []oss.ObjectProperties { | |||
return res | |||
} | |||
func PutObject(bucketName string, key string) { | |||
func PutObject(bucketName string, key string, fileBuffer *bytes.Buffer) { | |||
bucket := getBucket(bucketName) | |||
fileBuffer := bytes.NewBuffer(nil) | |||
err := bucket.PutObject(key, fileBuffer) | |||
if err != nil { | |||
panic(err) | |||
@@ -1,5 +1,5 @@ | |||
import React from "react"; | |||
import {Button, Col, Empty, Input, Popconfirm, Row, Spin, Tooltip, Tree} from 'antd'; | |||
import {Button, Col, Empty, Input, Popconfirm, Row, Spin, Tooltip, Tree, Upload} from 'antd'; | |||
import {CloudUploadOutlined, createFromIconfontCN, DeleteOutlined, EditOutlined, FolderAddOutlined, RadiusSettingOutlined} from "@ant-design/icons"; | |||
import * as Setting from "./Setting"; | |||
import * as FileBackend from "./backend/FileBackend"; | |||
@@ -86,9 +86,24 @@ class FileTree extends React.Component { | |||
}; | |||
} | |||
uploadFile(file, info) { | |||
const storeId = `${this.props.store.owner}/${this.props.store.name}`; | |||
// this.setState({uploading: true}); | |||
const filename = info.fileList[0].name; | |||
FileBackend.addFile(storeId, file.key, true, filename, info.file) | |||
.then(res => { | |||
Setting.showMessage("success", `File uploaded successfully`); | |||
window.location.reload(); | |||
}) | |||
.catch(error => { | |||
Setting.showMessage("error", `File failed to upload: ${error}`); | |||
}); | |||
}; | |||
addFile(file, newFolder) { | |||
const storeId = `${this.props.store.owner}/${this.props.store.name}`; | |||
FileBackend.addFile(storeId, file.key, newFolder) | |||
FileBackend.addFile(storeId, file.key, false, newFolder, null) | |||
.then((res) => { | |||
Setting.showMessage("success", `File added successfully`); | |||
window.location.reload(); | |||
@@ -303,10 +318,16 @@ class FileTree extends React.Component { | |||
}} /> | |||
</Tooltip> | |||
<Tooltip title={i18next.t("store:Upload file")}> | |||
<Button style={{marginRight: "5px"}} icon={<CloudUploadOutlined />} size="small" onClick={(e) => { | |||
Setting.showMessage("error", "Upload file"); | |||
e.stopPropagation(); | |||
}} /> | |||
<Upload maxCount={1} accept="*" showUploadList={false} beforeUpload={file => {return false;}} onChange={info => { | |||
this.uploadFile(file, info); | |||
}} | |||
> | |||
<Button style={{marginRight: "5px"}} icon={<CloudUploadOutlined />} size="small" /> | |||
</Upload> | |||
{/*<Button style={{marginRight: "5px"}} icon={<CloudUploadOutlined />} size="small" onClick={(e) => {*/} | |||
{/* Setting.showMessage("error", "Upload file");*/} | |||
{/* e.stopPropagation();*/} | |||
{/*}} />*/} | |||
</Tooltip> | |||
<Tooltip title={i18next.t("store:Delete")}> | |||
<span onClick={(e) => e.stopPropagation()}> | |||
@@ -404,7 +425,7 @@ class FileTree extends React.Component { | |||
); | |||
} | |||
if (["txt", "html", "js", "css", "md"].includes(ext)) { | |||
if (["txt", "htm", "html", "js", "css", "md"].includes(ext)) { | |||
if (this.state.loading) { | |||
return ( | |||
<div className="App"> | |||
@@ -9,10 +9,13 @@ export function updateFile(storeId, name, file) { | |||
}).then(res => res.json()); | |||
} | |||
export function addFile(storeId, key, newFolder) { | |||
return fetch(`${Setting.ServerUrl}/api/add-file?store=${storeId}&key=${key}&newFolder=${newFolder}`, { | |||
export function addFile(storeId, key, isLeaf, filename, file) { | |||
let formData = new FormData(); | |||
formData.append("file", file); | |||
return fetch(`${Setting.ServerUrl}/api/add-file?store=${storeId}&key=${key}&isLeaf=${isLeaf ? 1 : 0}&filename=${filename}`, { | |||
method: 'POST', | |||
credentials: 'include', | |||
body: formData, | |||
}).then(res => res.json()); | |||
} | |||