Download a file using fetch api - javascript

I am trying to download a file by clicking on a button it doesn't download the file. Although, if I go to the url on my browser then the docx is downloaded.
Fetch request:
const response = await fetch(`/template/${id}/docx`, {
method: 'GET',
credentials: 'include',
});
const blob = await response.blob();
const file = new File([blob], id, {type: blob.type, lastModified: Date.now()});
Response:

A fetch call either resolves with a Response object or rejects with an error. If you want the response body (which in your case is probably a binary blob) then you could try:
const response = await fetch(`/template/${id}/docx`, {
method: 'GET',
credentials: 'include',
});
const doc = await response.blob()
You would still have to take care of displaying it, writing it on the disk, whatever you want to do with it.

Related

Cloudflare Worker - Download a File using Fetch

I making a cloudflare worker that have to fetch a url pointing to a file. I want to redirect the request to download this file. The download happens, but with no extension and no name of the file. Can i read the response (return binary/octet-stream) and set the filename before download the file? Or some way to read the binary response and build a file with a name and download the file?
Im using fetch:
let file_response = await fetch(url)
.then((data) => {
}
thanks for the help!
After a while, i found a way. Maybe can help others!
var requestOptions = {
method: 'GET',
redirect: 'follow'
};
let file_response = await fetch(url,requestOptions)
let data = await file_response.blob();
contentDisposition = "attachment; filename=" + "file123.zip";
return new Response(data, {
status: 200,
headers: { "content-type": "application/octet-stream", "Content-Disposition": contentDisposition}
})
and now, the file is downloaded with the given name "file123.zip"

How to download remote image then upload image as an image file for form submission?

There are similar questions like this, this, this, and this, but none help.
In Node, the goal is to use the axios module to download an image from Twitter then upload this image as an image file as part of a form submission.
This code downloads the Twitter image, but the uploaded binary image is corrupted when it reaches the server (also our server).
The image must be uploaded in binary.
A form is required because other fields are also submitted with the binary image. These other form fields were removed to simplify the code sample.
const axios = require('axios');
const FormData = require('form-data');
let response = await axios.get('https://pbs.twimg.com/media/EyGoZkzVoAEpgp9.png', {
responseType: 'arraybuffer'
});
let imageBuffer = Buffer.from(response.data, 'binary');
let formData = new FormData();
formData.append('image', imageBuffer);
try {
let response = await axios({
method: 'post',
url: serverUrl,
data: formData,
});
// Do stuff with response.data
} catch (error) {
console.log(error)
}
You should pass the headers to the axios call using formData.getHeaders() to send a Content-Type header of multipart/form-data. Without it, a Content-Type header of application/x-www-form-urlencoded is sent. You could pass a responseType of stream to the axios call that downloads the image and add the stream to the form data.
You can also use axios.post to simplify the method call.
const url = 'https://pbs.twimg.com/media/EyGoZkzVoAEpgp9.png'
const { data: stream } = await axios.get(url, {
responseType: 'stream',
})
const formData = new FormData()
formData.append('image', stream)
try {
const { data } = await axios.post('http://httpbin.org/post', formData, {
headers: formData.getHeaders(),
})
console.log(data)
} catch (error) {
// handle error
}
You can use the fetch API to fetch the image as a blob object and append it to form data. Then simply upload it to its destination using Axios, ajax, or the fetch API:
const mediaUrl = "https://pbs.twimg.com/media/EyGoZkzVoAEpgp9.png"
fetch(mediaUrl)
.then((response) => response.blob())
.then((blob) => {
// you can also check the mime type before uploading to your server
if (!['image/jpeg', 'image/gif', 'image/png'].includes(blob?.type)) {
throw new Error('Invalid image');
}
// append to form data
const formData = new FormData();
formData.append('image', blob);
// upload file to server
uploadFile(formData);
})
.catch((error) => {
console.log('Invalid image')
});

Unable to get video file for S3 upload. (using Expo Camera)

I have been stuck with trying to upload a video to S3 for a while and was hoping to get some pointers. Currently, what I've read and was told is that we need to send an actual file to S3 and not the url (which we might do if we were sending it to the backend before aws).
I am trying to do this by
const getBlob = async (fileURi) => {
console.log('THIS IS IT', fileURi);
const resp = await fetch(fileURi);
const videoBody = await resp.blob();
console.log(videoBody);
};
getBlob(video.uri);
The problem I am having is I am unable to actually get the video file. When I stop recording a video with await camera.stopRecording(); what I get in return is
Object {
"uri": "file:///path/20DD0E08-11CA-423D-B83D-BD5ED40DFB25.mov",
}
Is there a recommended approach in order to successfully get the actual file in order to send it to S3 through the client?
The way I am trying to currently send the video which doesn't work is:
const formData = new FormData();
formData.append('file', video.uri);
await fetch(url, {
method: 'POST',
body: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
url: refers to the presignedUrl we get in return from aws.
P.S - Sending to the server through a fetch call does work but I noticed this approach also leave the User waiting for 10+ seconds since I need to send the video to the server then wait for it to finish uploading in AWS.
Thank you for all the help.
If I understand correctly you know how to upload file to your own server, but you want to send it directly to S3.
In that case I would suggest to use presigned URLs. https://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html
You can generate presigned URL on your backend, it is basically regular URL pointing to S3 file and some key values. You need to send those values to mobile app and do the same fetch call you are already using, but replace url with the one generated on backend and add all key-values to FormData.
Example for node backend would look like this
import AWS from 'aws-sdk';
...
const client = new AWS.S3(config);
...
const presignedUrl = client.createPresignedPost({
Bucket: 'example-bucket-name',
Fields: { key: 'example-file-name' },
});
and in mobile app you would
const form = new FormData();
Object.keys(presignedUrl.fields).forEach(key => {
form.append(key, presignedUrl.fields[key]);
})
form.append('file', fileToUpload);
await fetch(presignedUrl.url, {
method: 'POST',
body: form,
headers: {
'Content-Type': 'multipart/form-data'
}
})
My solutions. Please review the sample application. https://github.com/expo/examples/tree/master/with-aws-storage-upload
const response = await fetch(video.uri);
const blob = await response.blob();
const params = {
Bucket: myBucket,
Metadata: {
long: long.toString(),
lat: lat.toString(),
size: videoSize.toString()
},
Key: myKey,
Body: blob
};

How to retrieve an Image from img tag with remote url and create File object from it

Steps:
I have a remote image url.
I generated the img tag from it.
Now I want to read this img tag and convert it into a File object so that I can send it to server for upload.
Method 1 Tried: I have already tried the fetch method and directly tried to fetch image data from remote url.
Method 2 Tried:
clicked = () => {
const img = document.getElementById('someId');
const options = {
method: 'get',
headers: {
'Access-Control-Request-Headers': '*',
'Access-Control-Request-Method': '*',
},
mode: 'cors',
};
fetch(img.src, options)
.then(res => res.blob())
.then((blob) => {
const file = new File([blob], 'dot.png', blob);
console.log(file);
});
}
Expected output is File object.
I am using axios here but the principal should be the same:
const res = await axios.get(`/api/image/${imageId}`, {
responseType: 'arraybuffer'
});
const imgFile = new Blob([res.data]);
const imgUrl = URL.createObjectURL(imgFile);
Ignore the response type.

how to attach a file to request so that it shows up as request.files in python

The way I have found examples are:
const file = fs.readFileSync(filePath)
const formData = new FormData()
formData.append('userId', userId)
formData.append('file', file)
const options = {
method: 'post',
url: 'http://localhost:5000/uploadFile',
headers: {
'content-type': 'multipart/form-data'
},
data: formData
}
await axios(options).then(res => { console.log(res) }).catch(err => { console.log(err) })
But this doesn't attach the file in request.files which is required for python. Since it doesn't attach it as file, the information about file type is also lost.
I have also tried using the following. It does attach the file to request.files but the contents are not of the proper file and all I get is a text string which assumingely is a buffer string output.
const file = new File(fs.readFileSync(filePath), fileName, { type: 'text/csv' })
The aim is to preserve the file type information so that server can save the file properly. What am I missing?
Note that the requests are not sent from nodejs (which has file access) directly.

Categories