dropzone.js - 将目录和文件上传到 Spring MVC
dropzone.js - upload directories and files to Spring MVC
我可以使用 dropzone.js 将文件和文件夹内的文件上传到我的 Spring 控制器,但我没有得到带有拖动文件夹的文件。例如,如果我拖放包含 image1.jpg 和 image2.jpg 的目录 ~/media/,我得到的是 jpg 文件,但不是拖放的目录(在本例中是 [=38= .jpg).我需要能够允许拖放文件夹,以便可以上传 SD 卡并保持原始结构。
ProjectAjaxController:
@RestController("ProjectAjaxController")
@Validated
public class ProjectAjaxController extends BaseController {
private static final String INVALID_FILE_SUPPLIED_PLEASE_SELECT_A_FILE_TO_UPLOAD = "Invalid file supplied. Please select a file to upload. ";
@RequestMapping("/ajax/project/upload")
public AjaxResponse uploadProjectFilesAndFolders(MultipartHttpServletRequest request,
@RequestParam("projectPath") String projectPath,
@RequestParam("file") MultipartFile[] file) {
AjaxResponse ajaxResponse = new AjaxResponse();
if (file == null) {
this.userErrors.add(INVALID_FILE_SUPPLIED_PLEASE_SELECT_A_FILE_TO_UPLOAD);
logger.error(INVALID_FILE_SUPPLIED_PLEASE_SELECT_A_FILE_TO_UPLOAD);
ajaxResponse.setMessage(INVALID_FILE_SUPPLIED_PLEASE_SELECT_A_FILE_TO_UPLOAD);
ajaxResponse.setStatusCode(-2);
} else {
try {
for (MultipartFile multipartFile: file) {
logger.info("current file " + multipartFile.getmultipartFilename());
...
}
} catch (IOException ioe) {
this.userErrors.add("Unable to upload files ");
logger.warn("Unable to upload files. " + ioe.getMessage(), ioe);
ajaxResponse.setStatusCode(-2);
ajaxResponse.setMessage(String.join(" " + this.userErrors));
} catch (Exception e) {
this.userErrors.add("Error uploading files " + e.getMessage());
logger.warn("Error uploading files. " + e.getMessage(), e);
ajaxResponse.setStatusCode(-2);
ajaxResponse.setMessage(String.join(" " + this.userErrors));
}
}
return ajaxResponse;
}
}
网页内容:
jQuery(document).ready(function($) {
$(".search-display-block").each(function() {
var details = $(this).find(".portfolio-dropzone-details");
var portfolioPath = details.data("portfolio-path");
$(this).dropzone({
url: "/ajax/project/upload",
uploadMultiple: true,
parallelUploads: 20,
autoProcessQueue: true,
createImageThumbnails: false,
previewsContainer: "#template-preview",
maxFilesize: 4000,
timeout: 0,
webkitDirectory: true,
params: {
'projectPath': portfolioPath
},
success: function(file, response) {
console.dir(response);
if (response == null || response.statusCode != 200) {
//console.log("Error occurred uploading file");
var errorMessage = (response == undefined || response.message == undefined) ? "Error occurred uploading file " : response.message;
$("#dropzone-error-messsage-block").append("<span>" + errorMessage + "</span>");
} else {
console.log("Succesfully uploaded file ");
//console.dir(file);
}
},
uploadprogress: function(file, progress, bytesSent) {
var percent = round(progress, 2);
var progressParent = $(file.previewElement).find(".dz-progress");
var progressElement = $(file.previewElement).find(".dz-upload");
progressElement.html(percent + "%");
var size = progressParent.width() * (percent / 100);
progressElement.width(size + "px");
},
//Called just before each file is sent
sending: function(file, xhr, formData) {
//Execute on case of timeout only
xhr.ontimeout = function(e) {
var errorMessage = "The server timed out transfering file " + file.name + ". Please try again or contact your administrator.";
$("#dropzone-error-messsage-block").append("<span>" + errorMessage + "</span>");
};
}
});
});
});
.card {
transition: 0.3s;
}
.portfolio-container {
background-color: #1d3c5c;
}
.card-member-span {
padding-right: 1em;
}
.project-dialog {
overflow: auto;
background-color: #1d3c5c;
}
.portfolio-dialog {
overflow: auto;
background-color: #ffffff;
}
.dialog {
display: none;
}
.project-block {
padding-left: 0.25em;
padding-bottom: 0.25em;
margin-bottom: 0;
font-size: 14px;
font-weight: 400;
line-height: 1.42857143;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
}
.project-block.focus,
.project-block:focus,
.project-block:hover {
color: #333;
}
.project-block-primary {
color: #1d3c5c;
background-color: #ddd;
font-weight: 700;
}
.list-cards {
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
overflow-y: auto;
overflow-x: hidden;
margin: 0 4px;
padding: 0 4px;
z-index: 1;
min-height: 0;
border-radius: 1em;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.portfolio-card {
width: 100%;
min-height: 3em;
background-color: #ddd;
color: #000;
padding-left: 3px;
}
.list-card-members {
background-color: #ffffff;
padding: 0.5em;
}
.list-card-section {}
.list-card-project-section {
background-color: #ffffff;
}
.list-card {
margin-bottom: 0.5em;
background-color: #1d3c5c;
border-radius: 1em;
overflow: hidden;
}
/* Add rounded corners to the top left and the top right corner of the image */
img {
vertical-align: inherit;
}
/* On mouse-over, add a deeper shadow */
.card:hover {
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
}
/* Add some padding inside the card container */
.container {
padding: 2px 16px;
}
#board {
/* user-select: none; */
display: flex;
white-space: nowrap;
margin-bottom: 10px;
overflow-x: auto;
overflow-y: hidden;
padding-bottom: 10px;
position: relative;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.list {
/* background-color: #5b5353; */
background-color: #1d3c5c;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
max-height: 100%;
position: relative;
white-space: normal;
margin-top: 2px;
padding-left: 5px;
padding-right: 5px;
}
.board-menu-container,
.list {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
}
.list-wrapper {
width: 270px;
margin: 0 5px;
height: 100%;
display: inline-block;
vertical-align: top;
}
.search-filter {
padding-top: 5px;
padding-bottom: 5px;
display: none;
font-size: 12px;
}
.search-filter-block {
padding-top: 5px;
padding-bottom: 5px;
}
.search-filter-tag-block {
margin-top: 5px;
}
.search-filter-select {
height: 100%;
font-size: 12px;
}
.search-colour-button {
color: white;
padding: 0.5em 0.5em;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 12px;
margin: 4px 2px;
cursor: pointer;
border-radius: 1em;
-webkit-border-radius: 1em;
-moz-border-radius: 1em;
}
.search-colour-button.active {
box-shadow: inset 0 0 0 3px #b3b3b3, inset 0 5px 10px #e6e6e6;
font-weight: 800;
}
.project-card {
position: relative;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
border-radius: 1em;
overflow: hidden;
background-color: #1d3c5c;
min-height: 10%;
max-height: 90%;
min-width: 10%;
max-width: 90%;
margin: 1em;
}
.project-card-content {
background-color: #fff;
}
.portfolio-card-title {
font-weight: 600;
padding: 0.5em;
cursor: pointer;
}
.portfolio-projects-title {
font-weight: 600;
}
.search-tags-form {
margin: 4px 2px;
}
.list-header {
color: #ddd;
}
.list-header-name-assist {
text-shadow: 2px 2px 4px #000000;
}
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #ccc;
margin: 0px;
padding: 0;
}
.portfolio-dialog {
background-color: #1d3c5c;
color: #fff;
}
.portfolio-dialog-content {
background-color: #1d3c5c;
color: #ffffff;
}
dl {
margin-bottom: 3px;
}
.bg-dark {
color: #333333;
background-color: #ffffff;
}
.portfolio-card-content {
margin-bottom: 0.5em;
border-radius: 1em;
padding-top: 0.5em;
padding-bottom: 1em;
}
.fps-tag-block {
padding-left: 1em;
padding-right: 1em;
}
.portfolio-icon-list {
color: #000;
}
.ui-dialog {
background-color: #1d3c5c;
}
.ui-dialog-titlebar {
background-color: #1d3c5c;
color: #ddd;
border: 0px;
}
.ui-dialog-buttonpane {
background-color: #1d3c5c;
color: #ddd;
border: 0px;
}
.ui-dialog .ui-dialog-title {
text-align: center;
}
.ui-dialog-buttonset {
color: #1d3c5c;
}
.ui-dialog-titlebar-close {
color: #1d3c5c;
content: "X";
}
.ui-widget-content a {
color: #333333;
}
.portfolio-toggle:before {
content: "▸";
}
.portfolio-toggle.collapsed:before {
content: "▾";
}
.project-block-rounded {
border-radius: 0.5em;
padding: 0.25em;
margin: 0.25em;
}
.open-portfolio-dialog-btn {
cursor: pointer;
}
.portfolio-overview-btn {
cursor: pointer;
}
.media-capture-btn {
cursor: pointer;
}
#search-filter-block {
cursor: pointer;
}
.dl-horizontal dt {
text-align: left;
}
.dl-horizontal dd {
width: auto;
}
.portfolio-card-filter {
padding-left: 1em;
}
.portfolio-metadata {
color: #000;
}
.portfolio-overview {
color: #000;
}
.fixed-header {
position: fixed;
top: 0em;
background-color: #1d3c5c;
padding: 1em;
width: 270px;
text-align: center;
}
.sortable-list {
padding-bottom: 100px;
}
.search-highlighter {
border: 2px solid red;
}
.portfolio-specific-btn {
padding-right: 0.5em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1:jquery.min.js/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.js"></script>
<div class="container-fluid" id="core-content">
<div class="col-xs-12 portfolio-page">
<div class="col-xs-2 " style="">
<div>Success/Error info goes here</div>
<div id="dropzone-status-updates-block">
<div id="dropzone-error-messsage-block"></div>
<div id="dropzone-progress-block"></div>
</div>
<div id="template-preview"></div>
</div>
<div class="col-xs-10 portfolio-board-container">
<div id="portfolio-container" class="container-fluid portfolio-container" style="">
<form action="#" id="portfolio-form" name="portfolio-form" method="POST" class="">
<div class="board-canvas">
<div id="board" class="u-fancy-scrollbar js-no-higher-edits js-list-sortable ui-sortable">
<div class="js-list list-wrapper ">
<div class="list js-list-content">
<div class="list-header js-list-header u-clearfix is-menu-shown">
<div class="list-header-target js-editing-target"></div>
<h4 class="list-header-name-assist js-list-name-assist text-center" dir="auto">
Awaiting Approval
</h4>
</div>
<div class="sortable-list ui-sortable" data-column-id="awaitapprove" data-column-value="awaitapprove Awaiting Approval">
<div data-portfolio-path="Tennis" class="list-card js-member-droppable is-covered ui-droppable search-display-block sfilter ui-sortable-handle">
<div class="list-card-cover js-card-cover portfolio-card" style="background-color: #02bf6f;
color: #000000; ">
<span class="hidden portfolio-dropzone-details" data-portfolio-path="Tennis"></span>
<div class="portfolio-card-filter-block">
<div class="portfolio-card-title portfolio-card-filter-heading ">
<div class="accordion-toggle collapsed portfolio-toggle" data-toggle="collapse" data-parent="#portfolioAccordion" data-target="#portfolio5ac752e61c99a112046cf391" aria-expanded="false">
<span class="portfolio-accordion"></span>
<i class="fa fa-user-circle " aria-hidden="true" title="You are a member of this portfolio"></i>
<span class="archiware-archive-state" data-portfolio-path="Tennis"><i class="fa fa-database" aria-hidden="true" title="Has been archived"></i></span> Tennis
<span class="text-right"></span>
</div>
</div>
</div>
</div>
<div class="list-card-details text-center">
<div class="list-card-members js-list-card-members">
<div class="portfolio-icon-list " data-example-id="portfolio-icon-list">
<div class="btn-group portfolio-specific-btn portfolio-overview-btn" title="Portfolio Overview">
<a href="#" class="portfolio-overview">
<i class="fa fa-eye fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn portfolio-checklist-btn" title="Portfolio Checklist">
<a href="#" class="portfolio-checklist">
<i class="fa fa-list fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn open-portfolio-metadata-btn" data-dialog-id="5ac752e61c99a112046cf391" title="Portfolio Metadata">
<a href="#" class="portfolio-metadata">
<i class="fa fa-file-text fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn open-portfolio-forum-btn" data-dialog-id="5ac752e61c99a112046cf391" title="Portfolio Forum">
<a href="#" class="portfolio-forum">
<i class="fa fa-commenting fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
</div>
</div>
<div class="list-card-project-section">
<div class="project-block project-block-primary open-project-dialog-btn" name="open-project-dialog-btn" data-dialog-id="project-dialog-motion-5ac752e61c99a112046cf391">
Motion Sports: <span class="badge">1</span>
</div>
</div>
</div>
</div>
<div data-portfolio-path="Badminton" class="list-card js-member-droppable is-covered ui-droppable search-display-block sfilter ui-sortable-handle">
<div class="list-card-cover js-card-cover portfolio-card" style="background-color: #02bf6f;
color: #000000; ">
<span class="hidden portfolio-dropzone-details" data-portfolio-path="Badminton"></span>
<div class="portfolio-card-filter-block">
<div class="portfolio-card-title portfolio-card-filter-heading ">
<div class="accordion-toggle collapsed portfolio-toggle" data-toggle="collapse" data-parent="#portfolioAccordion" data-target="#portfolio5ac752e61c99a112046cf391" aria-expanded="false">
<span class="portfolio-accordion"></span>
<i class="fa fa-user-circle " aria-hidden="true" title="You are a member of this portfolio"></i>
<span class="archiware-archive-state" data-portfolio-path="Badminton"><i class="fa fa-database" aria-hidden="true" title="Has been archived"></i></span> Badminton
<span class="text-right"></span>
</div>
</div>
</div>
</div>
<div class="list-card-details text-center">
<div class="list-card-members js-list-card-members">
<div class="portfolio-icon-list " data-example-id="portfolio-icon-list">
<div class="btn-group portfolio-specific-btn portfolio-overview-btn" title="Portfolio Overview">
<a href="#" class="portfolio-overview">
<i class="fa fa-eye fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn portfolio-checklist-btn" title="Portfolio Checklist">
<a href="#" class="portfolio-checklist">
<i class="fa fa-list fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn open-portfolio-metadata-btn" data-dialog-id="5ac752e61c99a112046cf391" title="Portfolio Metadata">
<a href="#" class="portfolio-metadata">
<i class="fa fa-file-text fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn open-portfolio-forum-btn" data-dialog-id="5ac752e61c99a112046cf391" title="Portfolio Forum">
<a href="#" class="portfolio-forum">
<i class="fa fa-commenting fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
</div>
</div>
<div class="list-card-project-section">
<div class="project-block project-block-primary open-project-dialog-btn" name="open-project-dialog-btn" data-dialog-id="project-dialog-motion-5ac752e61c99a112046cf391">
Motion Sports: <span class="badge">1</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="js-list list-wrapper ">
<div class="list js-list-content">
<div class="list-header js-list-header u-clearfix is-menu-shown">
<div class="list-header-target js-editing-target"></div>
<h4 class="list-header-name-assist js-list-name-assist text-center" dir="auto">
Approved
</h4>
</div>
<div class="sortable-list ui-sortable" data-column-id="approved" data-column-value="approved Approved">
<div class="ui-sortable-handle">
</div>
</div>
</div>
</div>
<div class="js-list list-wrapper ">
<div class="list js-list-content">
<div class="list-header js-list-header u-clearfix is-menu-shown">
<div class="list-header-target js-editing-target"></div>
<h4 class="list-header-name-assist js-list-name-assist text-center" dir="auto">
Editing in Progress
</h4>
</div>
<div class="sortable-list ui-sortable" data-column-id="editinprog" data-column-value="editinprog Editing in Progress">
<div class="ui-sortable-handle">
</div>
</div>
</div>
</div>
<div class="js-list list-wrapper ">
<div class="list js-list-content">
<div class="list-header js-list-header u-clearfix is-menu-shown">
<div class="list-header-target js-editing-target"></div>
<h4 class="list-header-name-assist js-list-name-assist text-center" dir="auto">
Awaiting Graphics
</h4>
</div>
<div class="sortable-list ui-sortable" data-column-id="awaitgraph" data-column-value="awaitgraph Awaiting Graphics">
<div class="ui-sortable-handle">
</div>
</div>
</div>
</div>
<div class="js-list list-wrapper ">
<div class="list js-list-content">
<div class="list-header js-list-header u-clearfix is-menu-shown">
<div class="list-header-target js-editing-target"></div>
<h4 class="list-header-name-assist js-list-name-assist text-center" dir="auto">
Completed
</h4>
</div>
<div class="sortable-list ui-sortable" data-column-id="completed" data-column-value="completed Completed">
<div class="ui-sortable-handle">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="spacer-sml"></div>
</form>
</div>
</div>
</div>
<div class="row">
<div class="spacer-sml"></div>
</div>
</div>
我正在 chrome 上进行测试,发现并非所有浏览器都支持 webkit。我在输入字段中设置了 webkitdirectory。我只是不知道如何将文件夹名称附加到文件名。
我只是在寻找一种方法来获取被拖放的文件夹,而不是文件系统文件夹。
所以我终于弄清楚了如何使用 dropzone 函数 renameFile 获取与文件名一起传递的目录名:
renameFile: function (file) {
let newFilename = file.fullPath;
return newFilename;
},
是啊!太好了,我想。现在该文件被视为文件夹而不是文件,当我对文件执行 mkdirs 时,它会创建一个文件夹作为文件名,例如media/image1.jpg,我也尝试过 createNewFile 来创建一个带有文件名的目录。然后,当我尝试使用 BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream( projectFilePath )); 读取流时我收到错误:
java.io.FileNotFoundException: /Volumes/share/Project/Tennis/media/image1.jpg (Invalid argument)
您不会得到目录,那是用户 select 的来源。如果你这样做了,你会得到他们的全部 windows/users/ ect ect.
首先设置目录或让用户创建它们然后上传到它们
经过多次试验和错误后,我最终将目录添加到表单数据中,然后更改控制器,使其采用额外的参数。我还删除了 renameFile 方法。
js:
sending: function(file, xhr, formData) {
//Execute on case of timeout only
xhr.ontimeout = function(e) {
var errorMessage = "The server timed out transferring file " + file.name + ". Please try again or contact your administrator.";
$("#dropzone-error-messsage-block").append("<span>" + errorMessage + "</span>");
};
formData.append('fullPath', file.fullPath);
}
控制器:
@RequestMapping("/ajax/project/upload")
public AjaxResponse uploadProjectFilesAndFolders(MultipartHttpServletRequest request,
@RequestParam("projectPath") String projectPath,
@RequestParam("fullPath") String fullPath,
@RequestParam("file") MultipartFile[] file) {
我可以使用 dropzone.js 将文件和文件夹内的文件上传到我的 Spring 控制器,但我没有得到带有拖动文件夹的文件。例如,如果我拖放包含 image1.jpg 和 image2.jpg 的目录 ~/media/,我得到的是 jpg 文件,但不是拖放的目录(在本例中是 [=38= .jpg).我需要能够允许拖放文件夹,以便可以上传 SD 卡并保持原始结构。
ProjectAjaxController:
@RestController("ProjectAjaxController")
@Validated
public class ProjectAjaxController extends BaseController {
private static final String INVALID_FILE_SUPPLIED_PLEASE_SELECT_A_FILE_TO_UPLOAD = "Invalid file supplied. Please select a file to upload. ";
@RequestMapping("/ajax/project/upload")
public AjaxResponse uploadProjectFilesAndFolders(MultipartHttpServletRequest request,
@RequestParam("projectPath") String projectPath,
@RequestParam("file") MultipartFile[] file) {
AjaxResponse ajaxResponse = new AjaxResponse();
if (file == null) {
this.userErrors.add(INVALID_FILE_SUPPLIED_PLEASE_SELECT_A_FILE_TO_UPLOAD);
logger.error(INVALID_FILE_SUPPLIED_PLEASE_SELECT_A_FILE_TO_UPLOAD);
ajaxResponse.setMessage(INVALID_FILE_SUPPLIED_PLEASE_SELECT_A_FILE_TO_UPLOAD);
ajaxResponse.setStatusCode(-2);
} else {
try {
for (MultipartFile multipartFile: file) {
logger.info("current file " + multipartFile.getmultipartFilename());
...
}
} catch (IOException ioe) {
this.userErrors.add("Unable to upload files ");
logger.warn("Unable to upload files. " + ioe.getMessage(), ioe);
ajaxResponse.setStatusCode(-2);
ajaxResponse.setMessage(String.join(" " + this.userErrors));
} catch (Exception e) {
this.userErrors.add("Error uploading files " + e.getMessage());
logger.warn("Error uploading files. " + e.getMessage(), e);
ajaxResponse.setStatusCode(-2);
ajaxResponse.setMessage(String.join(" " + this.userErrors));
}
}
return ajaxResponse;
}
}
网页内容:
jQuery(document).ready(function($) {
$(".search-display-block").each(function() {
var details = $(this).find(".portfolio-dropzone-details");
var portfolioPath = details.data("portfolio-path");
$(this).dropzone({
url: "/ajax/project/upload",
uploadMultiple: true,
parallelUploads: 20,
autoProcessQueue: true,
createImageThumbnails: false,
previewsContainer: "#template-preview",
maxFilesize: 4000,
timeout: 0,
webkitDirectory: true,
params: {
'projectPath': portfolioPath
},
success: function(file, response) {
console.dir(response);
if (response == null || response.statusCode != 200) {
//console.log("Error occurred uploading file");
var errorMessage = (response == undefined || response.message == undefined) ? "Error occurred uploading file " : response.message;
$("#dropzone-error-messsage-block").append("<span>" + errorMessage + "</span>");
} else {
console.log("Succesfully uploaded file ");
//console.dir(file);
}
},
uploadprogress: function(file, progress, bytesSent) {
var percent = round(progress, 2);
var progressParent = $(file.previewElement).find(".dz-progress");
var progressElement = $(file.previewElement).find(".dz-upload");
progressElement.html(percent + "%");
var size = progressParent.width() * (percent / 100);
progressElement.width(size + "px");
},
//Called just before each file is sent
sending: function(file, xhr, formData) {
//Execute on case of timeout only
xhr.ontimeout = function(e) {
var errorMessage = "The server timed out transfering file " + file.name + ". Please try again or contact your administrator.";
$("#dropzone-error-messsage-block").append("<span>" + errorMessage + "</span>");
};
}
});
});
});
.card {
transition: 0.3s;
}
.portfolio-container {
background-color: #1d3c5c;
}
.card-member-span {
padding-right: 1em;
}
.project-dialog {
overflow: auto;
background-color: #1d3c5c;
}
.portfolio-dialog {
overflow: auto;
background-color: #ffffff;
}
.dialog {
display: none;
}
.project-block {
padding-left: 0.25em;
padding-bottom: 0.25em;
margin-bottom: 0;
font-size: 14px;
font-weight: 400;
line-height: 1.42857143;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
}
.project-block.focus,
.project-block:focus,
.project-block:hover {
color: #333;
}
.project-block-primary {
color: #1d3c5c;
background-color: #ddd;
font-weight: 700;
}
.list-cards {
-webkit-box-flex: 1;
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
overflow-y: auto;
overflow-x: hidden;
margin: 0 4px;
padding: 0 4px;
z-index: 1;
min-height: 0;
border-radius: 1em;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.portfolio-card {
width: 100%;
min-height: 3em;
background-color: #ddd;
color: #000;
padding-left: 3px;
}
.list-card-members {
background-color: #ffffff;
padding: 0.5em;
}
.list-card-section {}
.list-card-project-section {
background-color: #ffffff;
}
.list-card {
margin-bottom: 0.5em;
background-color: #1d3c5c;
border-radius: 1em;
overflow: hidden;
}
/* Add rounded corners to the top left and the top right corner of the image */
img {
vertical-align: inherit;
}
/* On mouse-over, add a deeper shadow */
.card:hover {
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);
}
/* Add some padding inside the card container */
.container {
padding: 2px 16px;
}
#board {
/* user-select: none; */
display: flex;
white-space: nowrap;
margin-bottom: 10px;
overflow-x: auto;
overflow-y: hidden;
padding-bottom: 10px;
position: relative;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.list {
/* background-color: #5b5353; */
background-color: #1d3c5c;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
max-height: 100%;
position: relative;
white-space: normal;
margin-top: 2px;
padding-left: 5px;
padding-right: 5px;
}
.board-menu-container,
.list {
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
}
.list-wrapper {
width: 270px;
margin: 0 5px;
height: 100%;
display: inline-block;
vertical-align: top;
}
.search-filter {
padding-top: 5px;
padding-bottom: 5px;
display: none;
font-size: 12px;
}
.search-filter-block {
padding-top: 5px;
padding-bottom: 5px;
}
.search-filter-tag-block {
margin-top: 5px;
}
.search-filter-select {
height: 100%;
font-size: 12px;
}
.search-colour-button {
color: white;
padding: 0.5em 0.5em;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 12px;
margin: 4px 2px;
cursor: pointer;
border-radius: 1em;
-webkit-border-radius: 1em;
-moz-border-radius: 1em;
}
.search-colour-button.active {
box-shadow: inset 0 0 0 3px #b3b3b3, inset 0 5px 10px #e6e6e6;
font-weight: 800;
}
.project-card {
position: relative;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
border-radius: 1em;
overflow: hidden;
background-color: #1d3c5c;
min-height: 10%;
max-height: 90%;
min-width: 10%;
max-width: 90%;
margin: 1em;
}
.project-card-content {
background-color: #fff;
}
.portfolio-card-title {
font-weight: 600;
padding: 0.5em;
cursor: pointer;
}
.portfolio-projects-title {
font-weight: 600;
}
.search-tags-form {
margin: 4px 2px;
}
.list-header {
color: #ddd;
}
.list-header-name-assist {
text-shadow: 2px 2px 4px #000000;
}
hr {
display: block;
height: 1px;
border: 0;
border-top: 1px solid #ccc;
margin: 0px;
padding: 0;
}
.portfolio-dialog {
background-color: #1d3c5c;
color: #fff;
}
.portfolio-dialog-content {
background-color: #1d3c5c;
color: #ffffff;
}
dl {
margin-bottom: 3px;
}
.bg-dark {
color: #333333;
background-color: #ffffff;
}
.portfolio-card-content {
margin-bottom: 0.5em;
border-radius: 1em;
padding-top: 0.5em;
padding-bottom: 1em;
}
.fps-tag-block {
padding-left: 1em;
padding-right: 1em;
}
.portfolio-icon-list {
color: #000;
}
.ui-dialog {
background-color: #1d3c5c;
}
.ui-dialog-titlebar {
background-color: #1d3c5c;
color: #ddd;
border: 0px;
}
.ui-dialog-buttonpane {
background-color: #1d3c5c;
color: #ddd;
border: 0px;
}
.ui-dialog .ui-dialog-title {
text-align: center;
}
.ui-dialog-buttonset {
color: #1d3c5c;
}
.ui-dialog-titlebar-close {
color: #1d3c5c;
content: "X";
}
.ui-widget-content a {
color: #333333;
}
.portfolio-toggle:before {
content: "▸";
}
.portfolio-toggle.collapsed:before {
content: "▾";
}
.project-block-rounded {
border-radius: 0.5em;
padding: 0.25em;
margin: 0.25em;
}
.open-portfolio-dialog-btn {
cursor: pointer;
}
.portfolio-overview-btn {
cursor: pointer;
}
.media-capture-btn {
cursor: pointer;
}
#search-filter-block {
cursor: pointer;
}
.dl-horizontal dt {
text-align: left;
}
.dl-horizontal dd {
width: auto;
}
.portfolio-card-filter {
padding-left: 1em;
}
.portfolio-metadata {
color: #000;
}
.portfolio-overview {
color: #000;
}
.fixed-header {
position: fixed;
top: 0em;
background-color: #1d3c5c;
padding: 1em;
width: 270px;
text-align: center;
}
.sortable-list {
padding-bottom: 100px;
}
.search-highlighter {
border: 2px solid red;
}
.portfolio-specific-btn {
padding-right: 0.5em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1:jquery.min.js/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.js"></script>
<div class="container-fluid" id="core-content">
<div class="col-xs-12 portfolio-page">
<div class="col-xs-2 " style="">
<div>Success/Error info goes here</div>
<div id="dropzone-status-updates-block">
<div id="dropzone-error-messsage-block"></div>
<div id="dropzone-progress-block"></div>
</div>
<div id="template-preview"></div>
</div>
<div class="col-xs-10 portfolio-board-container">
<div id="portfolio-container" class="container-fluid portfolio-container" style="">
<form action="#" id="portfolio-form" name="portfolio-form" method="POST" class="">
<div class="board-canvas">
<div id="board" class="u-fancy-scrollbar js-no-higher-edits js-list-sortable ui-sortable">
<div class="js-list list-wrapper ">
<div class="list js-list-content">
<div class="list-header js-list-header u-clearfix is-menu-shown">
<div class="list-header-target js-editing-target"></div>
<h4 class="list-header-name-assist js-list-name-assist text-center" dir="auto">
Awaiting Approval
</h4>
</div>
<div class="sortable-list ui-sortable" data-column-id="awaitapprove" data-column-value="awaitapprove Awaiting Approval">
<div data-portfolio-path="Tennis" class="list-card js-member-droppable is-covered ui-droppable search-display-block sfilter ui-sortable-handle">
<div class="list-card-cover js-card-cover portfolio-card" style="background-color: #02bf6f;
color: #000000; ">
<span class="hidden portfolio-dropzone-details" data-portfolio-path="Tennis"></span>
<div class="portfolio-card-filter-block">
<div class="portfolio-card-title portfolio-card-filter-heading ">
<div class="accordion-toggle collapsed portfolio-toggle" data-toggle="collapse" data-parent="#portfolioAccordion" data-target="#portfolio5ac752e61c99a112046cf391" aria-expanded="false">
<span class="portfolio-accordion"></span>
<i class="fa fa-user-circle " aria-hidden="true" title="You are a member of this portfolio"></i>
<span class="archiware-archive-state" data-portfolio-path="Tennis"><i class="fa fa-database" aria-hidden="true" title="Has been archived"></i></span> Tennis
<span class="text-right"></span>
</div>
</div>
</div>
</div>
<div class="list-card-details text-center">
<div class="list-card-members js-list-card-members">
<div class="portfolio-icon-list " data-example-id="portfolio-icon-list">
<div class="btn-group portfolio-specific-btn portfolio-overview-btn" title="Portfolio Overview">
<a href="#" class="portfolio-overview">
<i class="fa fa-eye fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn portfolio-checklist-btn" title="Portfolio Checklist">
<a href="#" class="portfolio-checklist">
<i class="fa fa-list fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn open-portfolio-metadata-btn" data-dialog-id="5ac752e61c99a112046cf391" title="Portfolio Metadata">
<a href="#" class="portfolio-metadata">
<i class="fa fa-file-text fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn open-portfolio-forum-btn" data-dialog-id="5ac752e61c99a112046cf391" title="Portfolio Forum">
<a href="#" class="portfolio-forum">
<i class="fa fa-commenting fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
</div>
</div>
<div class="list-card-project-section">
<div class="project-block project-block-primary open-project-dialog-btn" name="open-project-dialog-btn" data-dialog-id="project-dialog-motion-5ac752e61c99a112046cf391">
Motion Sports: <span class="badge">1</span>
</div>
</div>
</div>
</div>
<div data-portfolio-path="Badminton" class="list-card js-member-droppable is-covered ui-droppable search-display-block sfilter ui-sortable-handle">
<div class="list-card-cover js-card-cover portfolio-card" style="background-color: #02bf6f;
color: #000000; ">
<span class="hidden portfolio-dropzone-details" data-portfolio-path="Badminton"></span>
<div class="portfolio-card-filter-block">
<div class="portfolio-card-title portfolio-card-filter-heading ">
<div class="accordion-toggle collapsed portfolio-toggle" data-toggle="collapse" data-parent="#portfolioAccordion" data-target="#portfolio5ac752e61c99a112046cf391" aria-expanded="false">
<span class="portfolio-accordion"></span>
<i class="fa fa-user-circle " aria-hidden="true" title="You are a member of this portfolio"></i>
<span class="archiware-archive-state" data-portfolio-path="Badminton"><i class="fa fa-database" aria-hidden="true" title="Has been archived"></i></span> Badminton
<span class="text-right"></span>
</div>
</div>
</div>
</div>
<div class="list-card-details text-center">
<div class="list-card-members js-list-card-members">
<div class="portfolio-icon-list " data-example-id="portfolio-icon-list">
<div class="btn-group portfolio-specific-btn portfolio-overview-btn" title="Portfolio Overview">
<a href="#" class="portfolio-overview">
<i class="fa fa-eye fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn portfolio-checklist-btn" title="Portfolio Checklist">
<a href="#" class="portfolio-checklist">
<i class="fa fa-list fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn open-portfolio-metadata-btn" data-dialog-id="5ac752e61c99a112046cf391" title="Portfolio Metadata">
<a href="#" class="portfolio-metadata">
<i class="fa fa-file-text fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
<div class="btn-group portfolio-specific-btn open-portfolio-forum-btn" data-dialog-id="5ac752e61c99a112046cf391" title="Portfolio Forum">
<a href="#" class="portfolio-forum">
<i class="fa fa-commenting fa-1-5-font-size" aria-hidden="true"></i></a>
</div>
</div>
</div>
<div class="list-card-project-section">
<div class="project-block project-block-primary open-project-dialog-btn" name="open-project-dialog-btn" data-dialog-id="project-dialog-motion-5ac752e61c99a112046cf391">
Motion Sports: <span class="badge">1</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="js-list list-wrapper ">
<div class="list js-list-content">
<div class="list-header js-list-header u-clearfix is-menu-shown">
<div class="list-header-target js-editing-target"></div>
<h4 class="list-header-name-assist js-list-name-assist text-center" dir="auto">
Approved
</h4>
</div>
<div class="sortable-list ui-sortable" data-column-id="approved" data-column-value="approved Approved">
<div class="ui-sortable-handle">
</div>
</div>
</div>
</div>
<div class="js-list list-wrapper ">
<div class="list js-list-content">
<div class="list-header js-list-header u-clearfix is-menu-shown">
<div class="list-header-target js-editing-target"></div>
<h4 class="list-header-name-assist js-list-name-assist text-center" dir="auto">
Editing in Progress
</h4>
</div>
<div class="sortable-list ui-sortable" data-column-id="editinprog" data-column-value="editinprog Editing in Progress">
<div class="ui-sortable-handle">
</div>
</div>
</div>
</div>
<div class="js-list list-wrapper ">
<div class="list js-list-content">
<div class="list-header js-list-header u-clearfix is-menu-shown">
<div class="list-header-target js-editing-target"></div>
<h4 class="list-header-name-assist js-list-name-assist text-center" dir="auto">
Awaiting Graphics
</h4>
</div>
<div class="sortable-list ui-sortable" data-column-id="awaitgraph" data-column-value="awaitgraph Awaiting Graphics">
<div class="ui-sortable-handle">
</div>
</div>
</div>
</div>
<div class="js-list list-wrapper ">
<div class="list js-list-content">
<div class="list-header js-list-header u-clearfix is-menu-shown">
<div class="list-header-target js-editing-target"></div>
<h4 class="list-header-name-assist js-list-name-assist text-center" dir="auto">
Completed
</h4>
</div>
<div class="sortable-list ui-sortable" data-column-id="completed" data-column-value="completed Completed">
<div class="ui-sortable-handle">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="spacer-sml"></div>
</form>
</div>
</div>
</div>
<div class="row">
<div class="spacer-sml"></div>
</div>
</div>
我正在 chrome 上进行测试,发现并非所有浏览器都支持 webkit。我在输入字段中设置了 webkitdirectory。我只是不知道如何将文件夹名称附加到文件名。
我只是在寻找一种方法来获取被拖放的文件夹,而不是文件系统文件夹。
所以我终于弄清楚了如何使用 dropzone 函数 renameFile 获取与文件名一起传递的目录名:
renameFile: function (file) {
let newFilename = file.fullPath;
return newFilename;
},
是啊!太好了,我想。现在该文件被视为文件夹而不是文件,当我对文件执行 mkdirs 时,它会创建一个文件夹作为文件名,例如media/image1.jpg,我也尝试过 createNewFile 来创建一个带有文件名的目录。然后,当我尝试使用 BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream( projectFilePath )); 读取流时我收到错误:
java.io.FileNotFoundException: /Volumes/share/Project/Tennis/media/image1.jpg (Invalid argument)
您不会得到目录,那是用户 select 的来源。如果你这样做了,你会得到他们的全部 windows/users/ ect ect.
首先设置目录或让用户创建它们然后上传到它们
经过多次试验和错误后,我最终将目录添加到表单数据中,然后更改控制器,使其采用额外的参数。我还删除了 renameFile 方法。
js:
sending: function(file, xhr, formData) {
//Execute on case of timeout only
xhr.ontimeout = function(e) {
var errorMessage = "The server timed out transferring file " + file.name + ". Please try again or contact your administrator.";
$("#dropzone-error-messsage-block").append("<span>" + errorMessage + "</span>");
};
formData.append('fullPath', file.fullPath);
}
控制器:
@RequestMapping("/ajax/project/upload")
public AjaxResponse uploadProjectFilesAndFolders(MultipartHttpServletRequest request,
@RequestParam("projectPath") String projectPath,
@RequestParam("fullPath") String fullPath,
@RequestParam("file") MultipartFile[] file) {