I'm trying to load a JSON file from the user using this method:
<input
style="display: none"
type="file" (change)="onFileChanged($event)"
#fileInput>
<button (click)="fileInput.click()">Select File</button>
<button (click)="onUpload()">Upload!</button>
and this is the code in the component ts file:
export class MyFileUploadComponent {
selectedFile: File
onFileChanged(event) {
this.selectedFile = event.target.files[0];
console.log(this.selectedFile);
console.log('content: ' + JSON.stringify(this.selectedFile));
}
onUpload() {
// upload code goes here
}
}
the line console.log(this.selectedFile); does provide me with the file meta data which is:
lastModified: 1551625969247
lastModifiedDate: Sun Mar 03 2019 17:12:49 GMT+0200 (Israel Standard Time) {}
name: "manuscripts.json"
size: 6008
type: "application/json"
webkitRelativePath: ""
__proto__: File
But when I'm trying to print it's content using JSON.stringify I get: {} (empty file).
What's the cause?
Thanks.
But when I'm trying to print it's content using JSON.stringify I get: {} (empty file).
This is not a content of JSON file. It's a File object. To read content of JSON you need to use FileReader
onFileChanged(event) {
this.selectedFile = event.target.files[0];
const fileReader = new FileReader();
fileReader.readAsText(this.selectedFile, "UTF-8");
fileReader.onload = () => {
console.log(JSON.parse(fileReader.result));
}
fileReader.onerror = (error) => {
console.log(error);
}
}
JSON.Stringify does not work for File objects in TS/JS. You should extract data from File and then stringify it.
For examlple, extract file content as a string or array of strings using https://developer.mozilla.org/en-US/docs/Web/API/FileReader
Related
I am making an axios.post() request in my Vue component to send some formData holding a media File to upload through a PHP script. I know the file object is being appended correctly as I log the data before the request here:
// this.postMedia is a Vue array holding any post media objects to be uploaded
this.postMedia.forEach((mediaObj, index) => {
formData.append('media[' + index + ']', mediaObj.media);
formData.append('mediaType[' + index + ']', mediaObj.mediaType);
});
// Logging formData
for (let p of formData.values()) {
console.log(p);
}
This logs the information of the file object and the corresponding media type as expected.
// This is the media data
File {
lastModified: 1627299857401
lastModifiedDate: Mon Jul 26 2021 07:44:17 GMT-0400 (Eastern Daylight Time) {}
name: "test-image.jpg"
size: 12295
type: "image/jpeg"
webkitRelativePath: ""
}
// This is the mediaType data
1
I am then passing this data through an axios request and logging the response data as follows:
// Vue.js file
axios.post('/api/createPostV2', formData, config)
.then(success => {
console.log(success.data);
})
.catch(function(err) {
console.log(err.response);
});
// PHP file being requested (/api/createPostV2)
public static function createPostV2(Request $request)
{
// Just return request to check data
return $request->all();
}
Here is what gets logged:
media: Array(1)
0: {}
length: 1
[[Prototype]]: Array(0)
mediaType: ['1']
So it is passing the media array, but the actual file is not being passed as you can see by the empty object at index 0. As you can see the mediaType is passed correctly, keep in mind both 'media' and 'mediaType' are arrays to support uploading multiple files. Am I missing something here? Why is the file data being lost when I am passing it through formData?
As the title says, I have a client page that allows the user to upload files, they will always be .csv files.
export const sendFiles = async (files) => {
let form = new FormData();
form.append("arrFile", files);
await axios
.post(local + "/read-files", form, {
headers: { "Content-Type": "multipart/form-data" },
})
.then((res) => {
return res.data;
})
.catch((err) => {
return err;
});
};
This is the code I have for sending the files, using FormData. The files is an array of File objects. It can have just one or many. The files array on console looks like this
Array [ File ]
0: File { name: "filename.csv", lastModified: 1624560497968, size: 1244, … }
lastModified: 1624560497968
name: "filename.csv"
size: 1244
type: "application/vnd.ms-excel"
webkitRelativePath: ""
<prototype>: FilePrototype { name: Getter, lastModified: Getter, webkitRelativePath: Getter, … }
length: 1
<prototype>: Array []
I'm sending this to my Python Flask server
#app.route("/read-files", methods=['POST'])
def read_files():
if request.method == 'POST':
form = dict(request.form)
return
I found that the FormData is stored in request.form, but when I print this data on Python it shows as such.
{'arrFile': '[object File],[object File],[object File],[object File],[object File],[object File],[object File]'}
The files seem to be in a string separated by commas. What I'd like to do is be able to store these files and their content, and be able to read them afterwards. Is this possible?
if {your_file_name} in request.files:
file = request.files['your_file_name']
I'm changing an input file for a button that opens a new window using sweetAlert2
$('#btn-file').on('click', function (){
(async () =>{
let { value: file } = await Swal.fire({
title: 'Select image',
html: 'You can download a model for your work here',
input: 'file',
showCancelButton: true,
inputAttributes: {
'accept': '.csv',
'aria-label': 'Upload your CSV file'
}
})
if (file) {
const reader = new FileReader()
reader.onload = (e) => {
//CALL TO A FUNCTION
}
reader.readAsDataURL(file);
}
})();
});
I want to call my old function that it works correctly but is an input file
$("#csv-file").change(handleFileSelect);
function handleFileSelect(evt) {
var file = evt.target.files[0];
Papa.parse(file, {
//rest of my code....
I want to call to handleFileSelect, actually, that function runs when the input file has changes, I want to run with my sweetAlert
how can I do?
if I just only call to handleFileSelect(); I get this error
create:335 Uncaught TypeError: Cannot read property 'target' of undefined
Update to louys answer:
my Papa.parse(file) is not working, in the console.log for file I get this
console.log(file); when all is working
File {name: "task import.csv", lastModified: 1613002044713, lastModifiedDate: Wed Feb 10 2021 20:07:24 GMT-0400 (hora de Bolivia), webkitRelativePath: "", size: 96, …}
lastModified: 1613002044713
lastModifiedDate: Wed Feb 10 2021 20:07:24 GMT-0400 (hora de Bolivia) {}
name: "task import.csv"
size: 96
type: ""
webkitRelativePath: ""
__proto__: File
console.log(file); when I use the solution
data:application/octet-stream;base64,R29vZ2xlIFBsYWNlIFVSTCxCdXNpbmVzcyBUeXBlDQpodHRwOi8vd3d3LnJlc3RhdXJhbnQuY29tLFJlc3RhdXJhbnQNCmh0dHA6Ly93d3cuaG90ZWwuY29tLEhvdGVs
If I download that file link and put a .csv extension, the file is correct, but incompatible with Papa.parse
You don't need to use a FileReader here. If there is a file... Pass it to your function.
$('#btn-file').on('click', function (){
(async () =>{
let { value: file } = await Swal.fire({
title: 'Select image',
html: 'You can download a model for your work here',
input: 'file',
showCancelButton: true,
inputAttributes: {
'accept': '.csv',
'aria-label': 'Upload your CSV file'
}
})
if (file) {
//CALL TO A FUNCTION
handleFileSelect(file); // Try passing the file result directly
})();
});
function handleFileSelect(file) {
// Remove this... The file was passed as argument
//var file = evt.target.files[0];
//rest of my code....
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)
})
}
I have a react app that is the frontend for a laravel application. I am using a simple image uploader that returns the uploaded file to a post route. In the controller for the post route the request is coming in as a string and not the actual object. see my code.
onUpload = (picture) => {
this.setState({
pictures: this.state.pictures.concat(picture),
});
var curr = this
const formData = new FormData();
formData.append('file',picture)
console.log(picture[0])
axios
.post('/upload-subitem-image', formData, fileHeaders)
.then(function (response) {
const data = response.data
console.log(data)
})
.catch(error => {
console.log(error);
})
}
When i console the picture object I get
File {name: "test.png", lastModified: 1553443959805, lastModifiedDate: Sun Mar 24 2019 12:12:39 GMT-0400 (Eastern Daylight Time), webkitRelativePath: "", size: 11695, …}
But after passing it to laravel to try and get the file it returns a string when i try to do this.
$data = $request->File();
and looks like
{file:{"[object file]"}
Headers look like this:
const fileHeaders = {
'X-CSRF-TOKEN' : document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
'content-type': 'multipart/form-data',
'Accept': 'application/json',
}
Judging from the surrounding code, it looks like you're append-ing an array picture.
The API for FormData expects a File or Blob for file uploads so for an array it just turns it into a string. Since your array only has one item, it becomes [object file].
Try doing picture[0] in the append (And make sure to do proper bounds checks etc.)
Ref: https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects#Sending_files_using_a_FormData_object
Ended up adding some stuff to controller in php.
$data = $request->all();
$file = $data['file'];