I'm having an issue Updating a blobs name - I have done this no problem before but in this case I'm storing the blob in IndexedDB and based on certain conditions (save/saveas) it gets a name from Google Drive or you can add a new name.
Dom JS File
//Convert Text to Blob
let file = text;
fileName = "NewFileName";
let metadata = {
name: fileName, // Filename
mimeType: "application/pdf", // mimeType at Google Drive
};
let form = new FormData();
form.append(
"metadata",
new Blob([JSON.stringify(metadata)], { type: "application/json" })
);
form.append("file", file);
let textBlob = new Blob([file], {
'type': 'application/pdf',
});
Then My ServiceWorker Receives it and renames it then uploads it to google Drive
let blobPDF = request.result.text;
let blob = new Blob([blobPDF], {
type: "application/pdf"
});
let newBlob = new FormData();
console.log("Blob Name : " + saveas)
//Set New Name
newBlob.append("blob", blob, saveas);
fetch(
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id",
{
method: "POST",
headers: new Headers({ Authorization: "Bearer " + accessToken }),
body: blob // Also tried newBlob var -> Got not a blob error
}
)
if I use the var newBlob it says it's not a blob and errors - then changed to "file" it still doesn't set name
One obvious mistake is that you're sending the blob itself as the body of your fetch request, not the newBlob form data object with the filename.
fetch("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id", {
method: "POST",
headers: new Headers({ Authorization: "Bearer " + accessToken }),
body: newBlob
// ^^^^
})
If that doesn't help, I'd try creating a File instead of a Blob:
let blob = new File([blobPDF], saveas, {
type: "application/pdf"
});
Related
I am trying to open a PDF file in a new tab and want to read file without downloading it in local machine.
I tried this function, but it is not loading my pdf and giving error can not load pdf
function readFileInNewTab (fileId) {
let url = BASE_URL + "api/CMS/Documents/Download/" + fileId;
const requestOptions = {
method: 'GET',
headers: { 'Content-Type': 'application/pdf', ...authHeader(url) },
credentials: 'include',
responseType: "blob", // important
};
inProgress = true;
return fetch (url, requestOptions).then(handleResponse)
.then((response)=> {
const file = new Blob([response], { type: "application/pdf" });
//Build a URL from the file
const fileURL = URL.createObjectURL(file);
//Open the URL on new Window
debugger
const pdfWindow = window.open();
pdfWindow.location.href = fileURL;
})
.catch((error) => {
console.log(error);
});
} ```
Hi I am new to React Native, and I was trying to call my API hosted on Heroku my code is below:
const path = RNFS.ExternalDirectoryPath + '/newFile.jpg';
const handleUploadFile = async () => {
const token = await AsyncStorage.getItem('authtoken')
const file = await RNFS.readFile(path, "base64");
let url = `${host}/api/docs/add?card=${value}&number=${myFileId}`;
console.log(url);
let imageData = {
uri: path,
type: 'image/jpg', //the mime type of the file
name: 'newFile'
}
let formData = new FormData();
formData.append('file', imageData);
const response = await fetch(url, {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'authtoken': token,
'Content-Type': 'multipart/form-data'
},
body: formData
});
const output = await response.json();
console.log(output);
}
And while programming the server-side I tested my code as
But while calling API from react-native I was getting the below error:
Please help me in uploading file.
after you reciving the file as base64 you should convert it to a file and after that you can append it to your formData:
const base64File = await RNFS.readFile(path, "base64");
const blobResult = await fetch(base64File);
const file = new File([blobResult], "newFile",{ type: "image/jpg" });
const formData = new FormData();
formData.append('file', file);
In my React Native project i'm using react-native-image-picker for image upload. Here, i am using formData to upload image. Image URL is there, but when i console the formData it shows {}. I don't know why this is happening. Here's the code :
uploadImageAsync = async (imgUri, token) => {
let apiUrl = 'url';
let formData = new FormData();
let uriParts = imgUri.split('.');
let fileType = uriParts[uriParts.length - 1];
//generate some random number for the filename
var randNumber1 = Math.floor(Math.random() * 100);
var randNumber2 = Math.floor(Math.random() * 100);
formData.append('image', {
uri: imgUri,
name: `photo-${randNumber1}-${randNumber2}.${fileType}`,
type: `image/${fileType}`,
});
console.log('formData :', formData);
let options = {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
Authorization: 'Bearer ' + token,
'Content-Type': 'multipart/form-data',
'Cache-Control': 'no-cache',
},
};
const response = await fetch(apiUrl, options);
const json = await response.json();
}
};
Console of formData shows no data but imgUri consists image path. Why formData is showing no data?
The value property of FormData.append() can be either a USVString or a Blob.
Therefore, you can try stringifying your object and then optionally parse the string data.
const imageData = {
uri: imgUri,
name: `photo-${randNumber1}-${randNumber2}.${fileType}`,
type: `image/${fileType}`,
};
const formData = new FormData();
formData.append("image", JSON.stringify(imageData));
const formImageData = formData.get("image");
const parsedFormImageData = JSON.parse(formImageData);
console.log(parsedFormImageData );
I am getting the blob of an image from a URI to send it to my server to store it. I fetch the image using a get request and everything is correct, however, the post request has something wrong. The blob which is received by the server always have the size 0. I am sure that i get the blob of the image correct since i could display it in the frontend after converting the blob to base64.
Here is the code.
const url = "https://lh3.googleusercontent.com/a-/AOh14Gj1THuWiRu7Vpn85YETJN-aMui7NE8bpnNWOzdi"
var x, base64data;
const scope = this
var formData = new FormData();
var request = new XMLHttpRequest();
request.responseType = "blob";
request.onload = function () {
const blob = request.response
formData.append("file", blob.data);
console.log(blob.data)
//Converting the image to base64 so i could display it,
//and make sure that the blob received is not corrupted
const fileReaderInstance = new FileReader();
fileReaderInstance.readAsDataURL(blob);
fileReaderInstance.onload = () => {
base64data = fileReaderInstance.result;
scope.setState({base64data: base64data})
}
//Sending the blob to the server
x = new XMLHttpRequest();
x.open("POST",`${link}images/upload/${data.id}`,true);
x.setRequestHeader("Content-type", "image/jpeg");
x.setRequestHeader("Content-Length", formData.length);
x.send(formData);
}
request.open("GET", url);
request.send();
The console.log(blob.data) shows
Object {
"blobId": "69B8ACFE-5E31-4F16-84D8-002B17399F7E",
"name": "unnamed.jpg",
"offset": 0,
"size": 74054,
"type": "image/jpeg",
}
Ther Server-side code.
router.post('/upload/:id', upload.single('file'), async (req, res) => {
console.log(req.file)
const imgId = req.file.id
const id = req.params.id;
if (!id) return res.send({ error: "Missing playerID" });
if (!idValidator.isMongoId(id))
return res.send({ error: "Invalid Id" })
const player = await Player.findById(id)
if (!player)
return res.send({ error: "Player does not exists" })
const oldImg = player.photo;
if(oldImg && oldImg.toString() !== "5d3ae42c3f2b2c379c361652"){
await Images.findByIdAndDelete(oldImg)
}
player.photo = imgId;
const updatedPlayer = await Player.findByIdAndUpdate(id, player,{new:true})
return res.send({player: updatedPlayer,msg:"Photo Updated!"})
});
The console.log(req.file) shows the following.
{ fieldname: 'file',
originalname: 'unnamed.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
id: 5e780359fbea1452b8409a3e,
filename: '9cdeec500a17eccbb302d8571058da59.jpg',
metadata: null,
bucketName: 'images',
chunkSize: 261120,
size: 0,
md5: 'd41d8cd98f00b204e9800998ecf8427e',
uploadDate: 2020-03-23T00:31:21.640Z,
contentType: 'image/jpeg' }
After a long search i found this and it worked finalllllyyy!!!!
postPicture(data) {
const apiUrl = `${link}images/upload/${data.id}`;
const uri = "https://lh3.googleusercontent.com/a-/AOh14Gj1THuWiRu7Vpn85YETJN-aMui7NE8bpnNWOzdi";
const fileType = "jpeg";
const formData = new FormData();
formData.append('file', {
uri,
name: `photo.${fileType}`,
type: `image/${fileType}`,
});
const options = {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
};
return fetch(apiUrl, options);
}
I'm trying to upload a file with the Google Drive api, and I have the metadata correct, and I want to ensure that the actual file contents make it there. I have a simple page setup that looks like this:
<div id="upload">
<h6>File Upload Operations</h6>
<input type="file" placeholder='file' name='fileToUpload'>
<button id='uploadFile'>Upload File</button>
</div>
and I have a the javascript setup where the user is prompted to sign in first, and then they can upload a file. Here's the code: (currently only uploads the file metadata....)
let uploadButton = document.getElementById('uploadFile');
uploadButton.onclick = uploadFile;
const uploadFile = () => {
let ftu = document.getElementsByName('fileToUpload')[0].files[0];
console.dir(ftu);
gapi.client.drive.files.create({
'content-type': 'application/json;charset=utf-8',
uploadType: 'multipart',
name: ftu.name,
mimeType: ftu.type,
fields: 'id, name, kind'
}).then(response => {
console.dir(response);
console.log(`File: ${ftu.name} with MimeType of: ${ftu.type}`);
//Need code to upload the file contents......
});
};
First, I'm more familiar with the back end, so getting the file in bits from the <input type='file'> tag is a bit nebulous for me. On the bright side, the metadata is there. How can I get the file contents up to the api?
So According to some resources I've found in my three day search to get this going, the file simply cannot be uploaded via the gapi client. It must be uploaded through a true REST HTTP call. So let's use fetch!
const uploadFile = () => {
//initialize file data from the dom
let ftu = document.getElementsByName('fileToUpload')[0].files[0];
let file = new Blob([ftu]);
//this is to ensure the file is in a format that can be understood by the API
gapi.client.drive.files.create({
'content-type': 'application/json',
uploadType: 'multipart',
name: ftu.name,
mimeType: ftu.type,
fields: 'id, name, kind, size'
}).then(apiResponse => {
fetch(`https://www.googleapis.com/upload/drive/v3/files/${response.result.id}`, {
method: 'PATCH',
headers: new Headers({
'Authorization': `Bearer ${gapi.client.getToken().access_token}`,
'Content-Type': ftu.type
}),
body: file
}).then(res => console.log(res));
}
The Authorization Header is assigned from calling the gapi.client.getToken().access_token function, and basically this takes the empty object from the response on the gapi call and calls the fetch api to upload the actual bits of the file!
In your situation, when you upload a file using gapi.client.drive.files.create(), the empty file which has the uploaded metadata is created. If my understanding is correct, how about this workaround? I have experienced the same situation with you. At that time, I used this workaround.
Modification points:
Retrieve access token using gapi.
File is uploaded using XMLHttpRequest.
Modified script:
Please modify the script in uploadFile().
let ftu = document.getElementsByName('fileToUpload')[0].files[0];
var metadata = {
'name': ftu.name,
'mimeType': ftu.type,
};
var accessToken = gapi.auth.getToken().access_token; // Here gapi is used for retrieving the access token.
var form = new FormData();
form.append('metadata', new Blob([JSON.stringify(metadata)], {type: 'application/json'}));
form.append('file', ftu);
var xhr = new XMLHttpRequest();
xhr.open('post', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,name,kind');
xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
xhr.responseType = 'json';
xhr.onload = () => {
console.log(xhr.response);
};
xhr.send(form);
Note:
In this modified script, it supposes that Drive API is enabled at API console and the access token can be used for uploading file.
About fields, you are using id,name,kind. So this sample also uses them.
Reference:
gapi
If I misunderstand your question or this workaround was not useful for your situation, I'm sorry.
Edit:
When you want to use fetch, how about this sample script?
let ftu = document.getElementsByName('fileToUpload')[0].files[0];
var metadata = {
'name': ftu.name,
'mimeType': ftu.type,
};
var accessToken = gapi.auth.getToken().access_token; // Here gapi is used for retrieving the access token.
var form = new FormData();
form.append('metadata', new Blob([JSON.stringify(metadata)], {type: 'application/json'}));
form.append('file', ftu);
fetch('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,name,kind', {
method: 'POST',
headers: new Headers({'Authorization': 'Bearer ' + accessToken}),
body: form
}).then((res) => {
return res.json();
}).then(function(val) {
console.log(val);
});
With https://www.npmjs.com/package/#types/gapi.client.drive
const makeUploadUrl = (fileId: string, params: Record<string, boolean>) => {
const uploadUrl = new URL(
`https://www.googleapis.com/upload/drive/v3/files/${fileId}`
)
Object.entries({
...params,
uploadType: 'media',
}).map(([key, value]) => uploadUrl.searchParams.append(key, `${value}`))
return uploadUrl
}
const uploadDriveFile = async ({ file }: { file: File }) => {
const params = {
enforceSingleParent: true,
supportsAllDrives: true,
}
// create file handle
const { result } = await gapi.client.drive.files.create(params, {
// CAN'T have the upload type here!
name: file.name,
mimeType: file.type,
// any resource params you need...
driveId: process.env.DRIVE_ID,
parents: [process.env.FOLDER_ID],
})
// post the file data
await fetch(makeUploadUrl(result.id!, params), {
method: 'PATCH',
headers: new Headers({
Authorization: `Bearer ${gapi.client.getToken().access_token}`,
'Content-Type': file.type,
}),
body: file,
})
return result
})
}