Jan 27 2020 09:05 AM - edited Jan 27 2020 09:09 AM
Hey all,
I have been attempting to attach a file/image via a form on a SPFx webpart (more specifically, via an <
<input type="file" /> tag). The file/image is displayed as a paperclip icon on the SharePoint list, but when I click into the list item to view the image, it displays a broken link. Note that this is a form that takes in leave requests. See the following for the arrangement of the steps :
// This is my interface with the required data needed for a leave request on ILeaveRequestForm.ts
export interface ILeaveRequestForm {
request: [{
Employee: string;
StartDate: string;
EndDate: string;
LeaveType: string;
Reason: string;
Status: string;
}];
selectedLeaveType: string;
Attachments: File;
}
// This is the initialized state on ILeaveRequestForm.tsx
const initialState: ILeaveRequestForm = {
request: [{
Employee: '',
StartDate: '',
EndDate: '',
LeaveType: '',
Reason: '',
Status: 'Pending'
}],
selectedLeaveType: '',
Attachments: new File([""], "", { type: "text/plain",})
};
// This is the markup in the render method
public render(): React.ReactElement<any> {
<div className="form-row">
<div className="form-group col-md-12">
<label>Start Date <span className={styles.required}>*</span></label>
<input type="date" className="form-control" id="startDate" min={today.slice(0, 4) + "-01-01"} max={today.slice(0, 4) + "-12-31"} onBlur={this.validateWeekend} required />
</div>
<div className="form-group col-md-12">
<label>End Date <span className={styles.required}>* <small id="Message"></small></span></label>
<input type="date" className="form-control" id="endDate" min={today.slice(0, 4) + "-01-01"} max={today.slice(0, 4) + "-12-31"} onBlur={this.validateWeekend} required />
</div>
<div className="form-group col-md-12" id="fileBrowser2">
<label>Upload Schedule <span className={styles.required}>*</span></label>
<div className="custom-file">
<input type="file" className="custom-file-input" id="studyAttachment" onChange={this.handleFileUpload} required />
<label className="custom-file-label" id="fileName">Choose file</label>
</div>
</div>
</div>
}
// This is the script to handle the upload and adding to SharePoint List
private handleFileUpload = (event) => {
var file = event.target.value;
var file2 = (document.getElementById("studyAttachment") as HTMLInputElement).files[0];
var fileName = file.split("\\").pop();
document.getElementById("fileName").innerHTML = fileName;
var reader = new FileReader();
var dataURL;
reader.onload = () => {
dataURL = reader.result;
console.log(dataURL)
};
console.log("fileInfo: " + fileInfo);
reader.readAsDataURL(file2);
this.setState({ Attachments: new File([dataURL], file2.name, { type: file2.type }) });
}
private handleSubmit = (event) => {
event.preventDefault();
var ptoStDtTime = $("#ptoStartDate").val() + "T" + $("#ptoStartTime").val();
var ptoEdDtTime = $("#ptoEndDate").val() + "T" + $("#ptoEndTime").val();
var data = {
"Employee": this.props.currentUser,
"LeaveType": this.state.selectedLeaveType,
"StartDate": $("#startDate").val() != undefined ? $("#startDate").val() : ptoStDtTime,
"EndDate": $("#endDate").val() != undefined ? $("#endDate").val() : ptoEdDtTime,
"Reason": $("#reason").val() != undefined ? $("#reason").val() : '',
"Status": "Pending",
"Attachments": this.state.Attachments
};
//Log form data
console.log(data);
// Set correct absoluteUrl of SP site
const url = this.props.url;
let web = new Web(url);
//Insert into SP List
web.lists.getByTitle('Leave%20Request%20Form').items.add({
Employee: data.Employee,
StartDate: data.StartDate,
EndDate: data.EndDate,
LeaveType_x003a_Description: data.LeaveType,
Reason: data.Reason,
Status: data.Status
//Attachments: data.Attachments
}).then((iar: ItemAddResult) => {
// this will add an attachment to the item we just created
iar.item.attachmentFiles.add(data.Attachments.name, data.Attachments);
//refresh page
window.location.reload();
}).catch(e => { console.error(e); });
}
export default LeaveRequestForm;
Here are some images to outline the process:
Can anyone offer any assistance? Maybe I'm not understanding how to add attachments to a SharePoint List properly.
I also tried this method outlined here and I get the very same result: https://github.com/SharePoint/PnP-JS-Core/wiki/Working-With:-Attachments
Jan 27 2020 07:46 PM
Instead of reading the file as DataURL ,can you try using the method readAsArrayBuffer() with the reader object.
Jan 29 2020 07:16 AM
Solution
I tried your suggestion and it was not working out for me. I ended up doing some more in-depth research and testing and finally got it to work.
For those who are probably experiencing the same issue, here is the working code:
NB:
1. The markup in the render method remained the same
2. The images with the steps remained the same except after clicking attachment, the image finally displays.
// This is my interface with the required data needed for a leave request on ILeaveRequestForm.ts
export interface ILeaveRequestForm {
request: [{
Employee: string;
StartDate: string;
EndDate: string;
LeaveType: string;
Reason: string;
Status: string;
}];
selectedLeaveType: string;
Attachments: File;
}
// This is the initialized state on ILeaveRequestForm.tsx
const initialState: ILeaveRequestForm = {
request: [{
Employee: '',
StartDate: '',
EndDate: '',
LeaveType: '',
Reason: '',
Status: 'Pending'
}],
selectedLeaveType: '',
Attachments: new File([""], "", { type: "",})
};
// This is the script to handle the upload and adding to SharePoint List
private handleFileUpload = (event) => {
var file = event.target.value;
var fileInfo = (document.getElementById("attachment") as HTMLInputElement).files[0];
//Set file input with file name
var fileName = file.split("\\").pop();
document.getElementById("fileName").innerHTML = fileName;
this.setState({ Attachments: fileInfo });
}
private handleSubmit = (event) => {
event.preventDefault();
//Form validations
if (this.validateLeaveTaken()) {
event.preventDefault();
}
else {
console.log(this.state.Attachments);
var ptoStDtTime = $("#ptoStartDate").val() + "T" + $("#ptoStartTime").val();
var ptoEdDtTime = $("#ptoEndDate").val() + "T" + $("#ptoEndTime").val();
var data = {
"Employee": this.props.currentUser,
"LeaveType": this.state.selectedLeaveType,
"StartDate": $("#startDate").val() != undefined ? $("#startDate").val() : ptoStDtTime,
"EndDate": $("#endDate").val() != undefined ? $("#endDate").val() : ptoEdDtTime,
"Reason": $("#reason").val() != undefined ? $("#reason").val() : '',
"Status": "Pending",
"Attachments": this.state.Attachments
};
//Log form data
console.log(data);
console.log("Attachment data: " + data.Attachments);
// Set correct absoluteUrl of SP site
const url = this.props.url;
let web = new Web(url);
//Insert into SP List
web.lists.getByTitle('Leave%20Request%20Form').items.add({
Employee: data.Employee,
StartDate: data.StartDate,
EndDate: data.EndDate,
LeaveType_x003a_Description: data.LeaveType,
Reason: data.Reason,
Status: data.Status
}).then((iar: ItemAddResult) => {
//Upload attachment if any
if (data.Attachments != null) {
var toUpload = data.Attachments;
var r = new FileReader();
r.onloadend = (e) => {
var dataItems = e.target.result;
iar.item.attachmentFiles.add(toUpload.name, dataItems).then(() => {
alert();
});
};
r.readAsArrayBuffer(toUpload);
console.log("iar: " + iar);
}
//refresh page
window.location.reload();
}).catch(e => { console.error(e); });
}
}
Additionally, I tested with other file types such as word, excel, pdf, jpg and png and they all were accepted and uploaded to the SharePoint Attachments column in my list.
Aug 26 2020 01:49 AM
@Yarrah Can you please share the code? Thanks!
Jan 29 2020 07:16 AM
Solution
I tried your suggestion and it was not working out for me. I ended up doing some more in-depth research and testing and finally got it to work.
For those who are probably experiencing the same issue, here is the working code:
NB:
1. The markup in the render method remained the same
2. The images with the steps remained the same except after clicking attachment, the image finally displays.
// This is my interface with the required data needed for a leave request on ILeaveRequestForm.ts
export interface ILeaveRequestForm {
request: [{
Employee: string;
StartDate: string;
EndDate: string;
LeaveType: string;
Reason: string;
Status: string;
}];
selectedLeaveType: string;
Attachments: File;
}
// This is the initialized state on ILeaveRequestForm.tsx
const initialState: ILeaveRequestForm = {
request: [{
Employee: '',
StartDate: '',
EndDate: '',
LeaveType: '',
Reason: '',
Status: 'Pending'
}],
selectedLeaveType: '',
Attachments: new File([""], "", { type: "",})
};
// This is the script to handle the upload and adding to SharePoint List
private handleFileUpload = (event) => {
var file = event.target.value;
var fileInfo = (document.getElementById("attachment") as HTMLInputElement).files[0];
//Set file input with file name
var fileName = file.split("\\").pop();
document.getElementById("fileName").innerHTML = fileName;
this.setState({ Attachments: fileInfo });
}
private handleSubmit = (event) => {
event.preventDefault();
//Form validations
if (this.validateLeaveTaken()) {
event.preventDefault();
}
else {
console.log(this.state.Attachments);
var ptoStDtTime = $("#ptoStartDate").val() + "T" + $("#ptoStartTime").val();
var ptoEdDtTime = $("#ptoEndDate").val() + "T" + $("#ptoEndTime").val();
var data = {
"Employee": this.props.currentUser,
"LeaveType": this.state.selectedLeaveType,
"StartDate": $("#startDate").val() != undefined ? $("#startDate").val() : ptoStDtTime,
"EndDate": $("#endDate").val() != undefined ? $("#endDate").val() : ptoEdDtTime,
"Reason": $("#reason").val() != undefined ? $("#reason").val() : '',
"Status": "Pending",
"Attachments": this.state.Attachments
};
//Log form data
console.log(data);
console.log("Attachment data: " + data.Attachments);
// Set correct absoluteUrl of SP site
const url = this.props.url;
let web = new Web(url);
//Insert into SP List
web.lists.getByTitle('Leave%20Request%20Form').items.add({
Employee: data.Employee,
StartDate: data.StartDate,
EndDate: data.EndDate,
LeaveType_x003a_Description: data.LeaveType,
Reason: data.Reason,
Status: data.Status
}).then((iar: ItemAddResult) => {
//Upload attachment if any
if (data.Attachments != null) {
var toUpload = data.Attachments;
var r = new FileReader();
r.onloadend = (e) => {
var dataItems = e.target.result;
iar.item.attachmentFiles.add(toUpload.name, dataItems).then(() => {
alert();
});
};
r.readAsArrayBuffer(toUpload);
console.log("iar: " + iar);
}
//refresh page
window.location.reload();
}).catch(e => { console.error(e); });
}
}
Additionally, I tested with other file types such as word, excel, pdf, jpg and png and they all were accepted and uploaded to the SharePoint Attachments column in my list.