FormData not sending File object through Post request - javascript

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?

Related

Python server store csv file sent from React client

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']

azure storage upload image file and get its url to display with img tag

I want use azure file storage to store image file
and i can upload image file with below code
...
const uploadBlobResponse = await blockBlobClient.uploadFile('./test.png');
console.log('Blob was uploaded successfully. requestId: ', uploadBlobResponse);
And output is
Blob was uploaded successfully. requestId: {
etag: '"0x8D8FCCEC050FDB7"',
lastModified: 2021-04-11T09:46:59.000Z,
contentMD5: <Buffer a6 c1 b2 ef 44 0d 59 d2 33 43 ea c3 03 06 3f e3>,
clientRequestId: 'c261dccb-1b2f-4802-9768-c98bb59cc8b4',
requestId: '686eda5f-301e-00c0-49b7-2ead12000000',
version: '2020-06-12',
versionId: undefined,
date: 2021-04-11T09:46:58.000Z,
isServerEncrypted: true,
encryptionKeySha256: undefined,
encryptionScope: undefined,
errorCode: undefined,
'content-length': '0',
server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0',
'x-ms-content-crc64': 'F99Vk4U+TkE=',
body: undefined
}
So, I cannot get the image's public URL.
How I can do this?
BlockBlobClient has a url property that will give you the URL of the blob. Something like:
const uploadBlobResponse = await blockBlobClient.uploadFile('./test.png');
console.log('Blob was uploaded successfully. requestId: ', uploadBlobResponse);
console.log('Blob URL: ', blockBlobClient.url);
However, even though the URL is the public URL of the blob it may still result in 404 (Not Found) error if the blob is inside a blob container with Private ACL. You will need to use a Shared Access Signature URL of the blob with at least Read permission to view the blob by its URL.

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)
})
}

Posting image to laravel with Axios only passing [object file] as string

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'];

Upload JSON file using Angular 6

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

Categories