Download document on the same page when using antd upload - javascript

I am using antd's upload component to allow a user to upload a document. Now after the user has uploaded it, I also want to allow him to download the attachment just uploaded. I know the documentation explains this to do in the following way:
import { Upload, Button, Icon } from 'antd';
const props = {
action: '//jsonplaceholder.typicode.com/posts/',
onChange({ file, fileList }) {
if (file.status !== 'uploading') {
console.log(file, fileList);
}
},
defaultFileList: [{
uid: '1',
name: 'xxx.png',
status: 'done',
response: 'Server Error 500', // custom error message to show
url: 'http://www.baidu.com/xxx.png',
}],
};
ReactDOM.render(
<Upload {...props}>
<Button>
<Icon type="upload" /> Upload
</Button>
</Upload>,
mountNode
);
But I want to allow the download on the same page and don't want to open a new window on click. How could I do this? Is there a better way to approach this?

The default behavior is to open the file in a new window.
You can override this behavior by providing an onPreview prop for Upload:
onPreview: A callback function, will be executed when file link or preview icon is clicked.
<Upload
//...
onPreview={handlePreview}
>
Now write your own logic to download the file in handlePreview. You can find many examples online on how to achieve that.
const handlePreview = (file) => {
console.log(file);
// write how you want to download
}

Related

How can I prompt user to upload file from within a PrimeNG menuItem in angular

I have a menu item like this
items = [{
label: 'Upload', icon: 'pi pi-plus', command: (event) => { //get the event.target.file and pass it into a service that will manage the rest},
...
}]
So in the Html I am using the <p-menu> like this
<p-menu [model]="items"></p-menu>
And all the labels and icons are being displayed correctly. But how do I get the upload to open a prompt for file upload like a <input type='file'> so that I can get the event.target.file to pass to the service being called in the command?
As far as my research goes there is no feature in PrimeNg that makes this easier.
Inorder to prompt the user for a file upload I had to create an input file type and then get the files after calling the click() event on it
So in the menuItem I call the prompt which then calls the service.
items = [{label: 'Upload', icon: 'pi pi-plus', command: () => {upload_prompt( )}]
upload_prompt( ): void {
const input = document.createElement( 'input' );
input.type = 'file';
input.multiple = true;
input.onchange = () => {
let file = input.files as FileList;
file_upload_service( file )
}
input.click()
}
Hope this helps someone.

Get folder path/directory in react js using 'window.showDirectoryPicker'?

I am using Window.showDirectoryPicker for saving a file in particular directory.
https://developer.mozilla.org/en-US/docs/Web/API/window/showDirectoryPicker
I want to show the selected directory/path beside the 'Select path' button. Is that possible to get the path on selecting the folder.
function getNewFileHandle() {
const opts = {
types: [{
description: 'Text file',
accept: {'text/plain': ['.txt']},
}],
};
return window.showDirectoryPicker(opts);
}
return(
<Button onClick={getNewFileHandle}>Select path</Button>
)

React SPFx - Adding files to SharePoint list field using PnPjs

I'm building an application using SPFx Webpart with React. On one of my components I have a form that the user can fill out. I'm using PnPjs to push the user's responses into my list field. Everything works as expected.
I was looking at how to add a file or attachment field type to a list. I saw I can do it in the powerapps. So now in my "Product" list I have a field called attachments. When I attach files to that field from SharePoint's backend and then make a call to the list using PnPjs the attachment field does not return information about the files. But rather a boolean with a true or false.
pnp.sp.web.lists.getByTitle("Products").items.filter("Id eq '" + this.props.match.params.id + "'").top(1).get().then((items: any[]) => {
console.log(items);
}
So this works perfect and returns back the item which should have had the attachments from the code below. Now in my items console I get back Attachments: true or Attachments: false
I'm using react-dropzone to allow users to upload files. Using PnPjs how do I upload the files to that item?
Here is how I'm creating the item:
pnp.sp.web.lists.getByTitle("Requests").items.add({
Title: this.state.SuggestedVendor,
Client_x0020_Email: this.state.getEmail,
Created: this.state.startDate,
Attachments: //need help here
}
Here is my code for the dropdown files:
onDrop = (acceptedFiles) => {
console.log(acceptedFiles);
//Assuming this is where I do the logic
}
<Dropzone
onDrop={this.onDrop}
multiple
>
{({getRootProps, getInputProps, isDragActive}) => (
<div {...getRootProps()}>
<input {...getInputProps()} />
{isDragActive ? "Drop it like it's hot!" : 'Click me or drag a file to upload!'}
</div>
)}
</Dropzone>
And here is the response I get back from console.log(acceptedFiles);:
[File]
0: File {path: "John-Hancock-signature.png", name: "John-Hancock-signature.png", lastModified: 1590783703732, lastModifiedDate: Fri May 29 2020 13:21:43 GMT-0700 (Pacific Daylight Time), webkitRelativePath: "", …}
length: 1
I found this documentation here on how to push the files : https://pnp.github.io/pnpjs/sp/files/
You have to create the item, and then add an attachment to it.
You can add an attachment to a list item using the add method. This method takes either a string, Blob, or ArrayBuffer. pnp documentation
onDrop = (acceptedFiles) => {
acceptedFiles.forEach(file => {
const reader = new FileReader()
reader.onabort = () => console.log('file reading was aborted')
reader.onerror = () => console.log('file reading has failed')
reader.onload = async () => {
// get file content
const binaryStr = reader.result
// assume we have itemId
let itemId = 1;
let request = await sp.web.lists.getByTitle("Requests").items.getById(itemId)();
await request.attachmentFiles.add("file2.txt", "Here is my content");
}
reader.readAsArrayBuffer(file)
})
}

Is there a way to store a file in a React state?

I'm working on a project where I need to store an image in my components state, so that I can send the file and accompanying data to a different component that uploads the data to my Firebase Database and the image to my Firestore.
I've tried doing it by setting the state the normal way, using a functions that is called when an image is submitted. But the state in which I want to pass on the file remains empty.
The initial state:
state = {
title: '',
description: '',
date: '',
ticket: '',
price: '',
image: []
}
The input:
<input type="file" id="image" accept="image/*" onChange={this.handleChangeImage} />
The function that is supposed to handle my problem:
handleChangeImage = (e) => {
const file = e.target.files[0];
this.setState({
[e.target.id]: file
});
}
If I console log the variable "file" I get the file, but console logging state.image will just show me an empty array.
Try changing your handle function to this:
handleChangeImage = (e) => {
const file = e.target.files[0];
const newImages = [...this.state.image];
newImages.push(file);
this.setState({
image: newImages
});
}
This problem is now resolved. I am an idiot. My problem wasn't that the state wasn't updated with the file, the problem was that the console log output happened before the state was updated with the file.
The state was always updated with the file, I just never realised.
The issue was in other words not an issue, just a plain dumb rookie mistake.

Antd upload's Dragger component upload occurs across domains

I use create-react-app to do my front end, and use the Dragger component inside antd's upload. My backend is springboot. My front end sends request data to the backend using fetch, which will cause cross-domain problems. So I added "proxy" in the package.json file of create-react-app: "http://localhost:8080" to proxy my backend, which solves the trouble of cross-domain, but when I use antd official website The uploader's Dragger component always reports an error when uploading.
This is my code for using Antd's Dragger.
import React, { Component } from 'react';
import { Upload, Icon, message } from 'antd';
import './UpVideo.css';
const Dragger = Upload.Dragger;
export default class UpVideo extends Component {
render(){
const props = {
name: 'file',
multiple: false,
headers:{
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods':'POST',
},
action: 'http://localhost:8080/vidoe/up',
onChange(info) {
// const status = info.file.status;
console.log(info);
// if (status !== 'uploading') {
// console.log(info.file, info.fileList);
// }
// if (status === 'done') {
// message.success(`${info.file.name} file uploaded successfully.`);
// } else if (status === 'error') {
// message.error(`${info.file.name} file upload failed.`);
// }
},
};
return(
<div>
<Dragger {...props}>
<p className="ant-upload-drag-icon">
<Icon type="inbox" />
</p>
<p className="ant-upload-text">点击或者拖动视频文件到这里</p>
</Dragger>,
</div>
)
}
}
This is the picture I gave the error.
I am sorry, I just learned to use StackOverflow. If my description is not clear, please let me know, this question has been annoying me for a long time, thank you.
This error is a security measure of google chrome. It appears when you use a 2 different servers for front and back end. install this library to fix it:
npm install cors
https://www.npmjs.com/package/cors

Categories