Skip to content

Commit b01c007

Browse files
committed
reverted code to include webkitGetAsEntry and getAsEntry method with defensive code condition to include when exists in browser.
1 parent 1cd349a commit b01c007

File tree

3 files changed

+81
-11
lines changed

3 files changed

+81
-11
lines changed

docs/documentation/docs/controls/DragDropFiles.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,15 @@ import { DragDropFiles } from "@pnp/spfx-controls-react/lib/DragDropFiles";
4848

4949
![FilePicker control with grouping](../assets/DragDropFilesSample2.png)
5050

51-
- With the `onDrop` handler you can define a method that returns files that where drag and drop by user.
51+
- With the `onDrop` handler you can define a method that returns files and files inside folders that where drag and drop by user.
5252

53+
**PS: New property "fullPath" was included in file object to allow identify dropped files based on Folders, this allow users to create associated folder path.**
5354

5455
```typescript
5556
private _getDropFiles = (files) => {
5657
for (var i = 0; i < files.length; i++) {
5758
console.log("Filename: " + files[i].name);
59+
console.log("Path: " + files[i].fullPath);
5860
}
5961
}
6062
```

src/controls/dragDropFiles/DragDropFiles.tsx

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,27 +102,94 @@ export class DragDropFiles extends React.Component<IDragDropFilesProps, IDragDro
102102
}
103103

104104
/**
105-
* Add File to Array Files of type File[]
106-
* @param dataTransfer
107-
*/
105+
* Add File to Array Files of type File[]
106+
* https://www.meziantou.net/upload-files-and-directories-using-an-input-drag-and-drop-or-copy-and-paste-with.htm
107+
* @param dataTransfer
108+
*/
108109
private getFilesAsync = async (e) => {
109110
const Customfiles = e.dataTransfer;
110111
const items = Customfiles.items;
112+
const Directory = [];
113+
let entry:any;
111114
const files: File[] = [];
112-
113115
for (let i = 0; i < items.length; i++) {
114116
const item = items[i];
115117
if (item.kind === "file") {
116-
const file = item.getAsFile();
117-
if (file) {
118-
files.push(file);
118+
/**
119+
* This method retrieves Files from Folders
120+
* defensive code to only use method when exist in browser if not only return files.
121+
* https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/webkitGetAsEntry
122+
*/
123+
if (item.getAsEntry) {
124+
entry = item.getAsEntry();
125+
Directory.push(entry);
126+
} else if (item.webkitGetAsEntry) {
127+
entry = item.webkitGetAsEntry();
128+
Directory.push(entry);
129+
} else if ("function" == typeof item.getAsFile) {
130+
const file = item.getAsFile();
131+
if (file) {
132+
file.fullPath = "";
133+
files.push(file);
134+
}
119135
}
120136
continue;
121137
}
122138
}
139+
if (Directory.length > 0) {
140+
const entryContent = await this.readEntryContentAsync(Directory);
141+
files.push(...entryContent);
142+
}
123143
return files;
124144
}
125145

146+
// Returns a promise with all the files of the directory hierarchy
147+
/**
148+
*
149+
* @param entry
150+
*/
151+
private readEntryContentAsync = (Directory) => {
152+
return new Promise<File[]>((resolve, reject) => {
153+
let reading = 0;
154+
const contents: File[] = [];
155+
Directory.forEach(entry => {
156+
readEntry(entry, "");
157+
});
158+
159+
function readEntry(entry, path) {
160+
if (entry.isDirectory) {
161+
readReaderContent(entry.createReader());
162+
} else {
163+
reading++;
164+
entry.file(file => {
165+
reading--;
166+
file.fullPath = path;
167+
contents.push(file);
168+
169+
if (reading === 0) {
170+
resolve(contents);
171+
}
172+
});
173+
}
174+
}
175+
176+
function readReaderContent(reader) {
177+
reading++;
178+
179+
reader.readEntries((entries) => {
180+
reading--;
181+
for (const entry of entries) {
182+
readEntry(entry, entry.fullPath);
183+
}
184+
185+
if (reading === 0) {
186+
resolve(contents);
187+
}
188+
});
189+
}
190+
});
191+
}
192+
126193
/**
127194
* Default React component render method
128195
*/

src/webparts/controlsTest/components/ControlsTest.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,8 @@ export default class ControlsTest extends React.Component<IControlsTestProps, IC
483483
*/
484484
private _getDropFiles = (files) => {
485485
for (var i = 0; i < files.length; i++) {
486-
console.log("File name: " +files[i].name);
486+
console.log("File name: " + files[i].name);
487+
console.log("Folder Path: " + files[i].fullPath);
487488
}
488489
}
489490

@@ -1200,8 +1201,8 @@ export default class ControlsTest extends React.Component<IControlsTestProps, IC
12001201
>
12011202

12021203
<Placeholder iconName='BulkUpload'
1203-
iconText='Drag files here...'
1204-
description={defaultClassNames => <span className={defaultClassNames}>Drag files here...</span>}
1204+
iconText='Drag files or folder with files here...'
1205+
description={defaultClassNames => <span className={defaultClassNames}>Drag files or folder with files here...</span>}
12051206
buttonLabel='Configure'
12061207
hideButton={this.props.displayMode === DisplayMode.Read}
12071208
onConfigure={this._onConfigure} />

0 commit comments

Comments
 (0)