The below code is what take final action to save the data to the target DB.
const onFileUpload = (e) => {
const files = Array.from(e.target.files);
const formData = new FormData();
formData.append('attachable_type', attachableType);
formData.append('attachable_id', attachableId);
if (files.length > 0) {
const file = files[0];
formData.append('file', file);
upload(dispatch, {
body: formData,
}).then(() => {});
}
};
Now I am building an offline app, where when no internet is available I would like to save this request to indexdb. I have the whole setup. All I want to know how can I save a FormData instance to indexdb so that I can later fetch it from indexdb and send it to server for permanent storage. I need some ideas. I tried some google but I don't see any direct answer to the following question. I am using idb npm plugin. The below update function I will be using to as an interface to talk to the db.
export async function update(attrs) {
const db = await createAppDB();
const tx = db.transaction('attachments', 'readwrite');
const store = tx.objectStore('attachments');
store.put(attrs);
await tx.done;
}
You could extract the FormData through the Body.formData() method, and then retrieve its content by getting this FormData's entries and store these to IDB:
(async () => {
// in ServiceWorker while disconnected
const request = buildRequest();
// extract the FormData
const fd = await request.formData();
const serialized = {
url: request.url,
method: request.method,
mode: request.mode,
body: [ ...fd ]
// you may need more fields from request
};
// you can now store the entries in IDB
// here we just log it
console.log( "stored", serialized );
// and to build back the Request
const retrieved = { ...serialized };
const new_body = new FormData();
for( let [ key, value ] of retrieved.body ) {
new_body.append( key, value );
}
retrieved.body = new_body;
const new_request = new Request( retrieved );
// fetch( new_request );
// remember to remove from IDB to avoid posting it multiple times
console.log( "sent", [...new_body] );
} )();
// returns the same kind of Request object a ServiceWorker would intercept,
// whose body is a FormData
function buildRequest() {
const fd = new FormData();
fd.append( "some-key", "some-data" );
fd.append( "the-file", new Blob( [ "hey" ] ), "file.txt" );
return new Request( "", { method: "POST", body: fd } );
}
Too bad we can't just put POST requests in the Cache API, it would have been a lot cleaner...
As far as I know, you cannot store any FormData into IndexedDB directly. In my case, I had to implement photo uploading for an offline app. I saved images into IndexedDB in base64 format with some other data and then uploaded them on the server once the internet connection is restored.
Related
Hello All I hope All Are Doing Well
I have A issue I am uploading multiple images in Cloudinary via ReactJs
Here Is Input Field
<input
type="file"
className="form-control"
required
onChange={(e) => setImages(e.target.files)}
multiple
/>
OnChange I'm storing all files on a state given below
const [images, setImages] = useState([]);
Now I am looping the state and uploading each file to Cloudinary and extracting the URL of each Image code is given below
for (const file of images) {
async function upload() {
const formData = new FormData();
formData.append("file", file);
formData.append("upload_preset", "DummyPreset"); // Replace the preset name with your own
formData.append("api_key", "0300545648961"); // Replace API key with your own Cloudinary key
// Make an AJAX upload request using Axios (replace Cloudinary URL below with your own)
await axios
.post(
"https://api.cloudinary.com/v1_1/Dummycloud/image/upload",
formData,
{
headers: { "X-Requested-With": "XMLHttpRequest" },
}
)
.then((response) => {
const data = response.data;
const fileURL = data.secure_url; // You should store this URL for future references in your app
console.log(fileURL);
});
}
upload();
}
Here I'm able to extract each link As fileURL and consoled it
console.log(fileURL);
To See The Output Please click the Link it will redirects you to the image Outputimage
As You Can see all URLs Are Extracted Now I want to push All Extracted URLs into an Array And Wants to send them to Express Server where I'll store them into DB
Please Let Me Know How Store All URLs into a state array whenever any URL extracted it'll be stored into That array
Here's The Solution
Thanks For Contribution
var ImagesUrlArray = [];
for (const file of image) {
async function upload() {
const formData = new FormData();
formData.append("file", file);
formData.append("upload_preset", "DummyPreset"); // Replace the preset name with your own
formData.append("api_key", "0300545648961"); // Replace API key with your own Cloudinary key
// Make an AJAX upload request using Axios (replace Cloudinary URL below with your own)
await axios
.post(
"https://api.cloudinary.com/v1_1/Dummycloud/image/upload",
formData,
{
headers: { "X-Requested-With": "XMLHttpRequest" },
}
).then((response) => {
const data = response.data;
var fileURL = data.secure_url; // You should store this URL for future references in your app
ImagesUrlArray = [...ImagesUrlArray];
ImagesUrlArray.push(fileURL);
if (ImagesUrlArray.length === image.length) {
const res = axios
.post("http://localhost:5000/register", {
fullname: Data.fullname,
email: Data.email,
pass: Data.pass,
cpass: Data.cpass,
phone: Data.phone,
imagee: ImagesUrlArray,
})
.then((response) => response);
setdataa(res);
}
});
}
upload();
}
// this function returns a Promise
const uploadFile = (file) => {
const formData = new FormData();
formData.append(stuff);
return axios.post('some/path', formData).then(response => response.data.secure_url);
};
Promise.all(images.map(uploadFile)).then(fileURLs => storeFileURLs(fileURLs))
i have a bunch of VHD files stored on a private Server, which are accessible through a url.
I am trying upload these vhd files directly to my azure storage account using the azure javascript npm libraries. The vhds have to be uploaded as page-blobs. I tried using the method uploadPagesFromURL() of the pageblobClient but with no success. My code looks roughly like this:
async function uploadVHD(accessToken, srcUrl)
{
try {
// Get credentials from accessToken
const creds = new StorageSharedKeyCredential(storageAccount.name, storageAccount.key);
// Get blobServiceClient
const blobServiceClient = new BlobServiceClient(`https://${storageAccount.name}.blob.core.windows.net`, creds);
// Create Container
const containerClient = blobServiceClient.getContainerClient("vhd-images");
await containerClient.createIfNotExists();
const src = srcUrl.replace('https://', 'https://username:password#');
// Upload to blob storage
const pageBlobClient = containerClient.getPageBlobClient("Test.vhd");
// Get fileSize of vhd
const fileSize = (await axiosRequest(src, { method: "HEAD" })).headers["content-length"];
const uploadResponse = await pageBlobClient.uploadPagesFromURL(src, 0, 0, fileSize);
return uploadResponse;
} catch (error) {
return error;
}
});
It is not possible to upload the Page Blob with your URL directly. You need to read data from the url. Then upload using uploadPages method.
axios.get(URL, {
responseType: 'arraybuffer'
})
.then((response) => {
console.log(response.data)
console.log(response.data.length)
// upload page blob...
}).catch((error) => {
//handle error
});
// uploadPages method
const uploadResponse = pageBlobClient.uploadPages(data, 0, dataLength);
In my application, the user uploads a CSV file in the website, and I need to update the file content (add a few columns) and send it to an API.
So far, I am able to read the file, and transform the CSV content into a JSON object, but I'm stuck in the process of updating the file content and sending it to the API (which needs to receive an object of type File). However, the way that I found is transforming the CSV into an encodeURI.
This is the code:
import { post } from "axios";
class UploadAdmin extends Component {
constructor(props) {
super(props);
// ...
}
onFormSubmit(e) {
if (this.state.file != null) {
e.preventDefault();
// adding the missing columns to the JSON object
const csvObject = this.state.parsedCsvFile;
csvObject["Campaign Name"] = this.state.campaign_name;
csvObject["Campaign Code"] = this.state.campaign_code;
const rows = [Object.keys(csvObject), Object.values(csvObject)];
let csvContent =
"data:text/csv;charset=utf-8," +
rows.map((e) => e.join(";")).join("\n");
// creating CSV file (here the error is happening, since I need to create an object
// with File type to send to the fileUpload() function, but I'm creating an URI)
var newFile = encodeURI(csvContent);
this.fileUpload(newFile)
.then((resp) => {
this.onClear();
this.setState({ modal: true, tipo: "success" });
this.props.getListImport();
})
.catch((error) => {
// handling errors...
} else {
this.onClear();
}
}
fileUpload(file) {
const BASE_URL = `${window.REACT_APP_URL}`;
const formData = new FormData();
formData.append("file", file);
const config = {
headers: {
"content-type": "multipart/form-data",
},
};
return post(`${BASE_URL}/file`, formData, config);
}
Thanks in advance.
To be honest I'm still confused about this, but I don't have time right now. The following may or may not work:
fileUpload(file) {
const BASE_URL = `${window.REACT_APP_URL}`;
const searchParams = new URLSearchParams();
searchParams.append("file", file);
const config = {
headers: {
"content-type": "multipart/form-data",
},
};
const file = new File(searchParams.toString(), "my-file",
{ type: "multipart/form-data" });
return post(`${BASE_URL}/file`, file, config);
}
I changed the FormData to a URLSearchParams. They seem to be very similar types, but URLSearchParams has a toString method which I've called. Then I made it into a File because you said this was necessary, although I'm not convinced that it is. I also renamed it from formData to searchParams.
I'm saving an image file locally so I can ready it using fs.createReadStream() and append it to my FormData to send it to a REST api. Like this: (I'm using the trello api https://developer.atlassian.com/cloud/trello/rest/#api-cards-id-attachments-post)
const fetch = require('node-fetch');
const Jimp = require('jimp');
const FormData = require('form-data');
// Save file locally
await Jimp.read(imagePNGURL).writeAsync(savedImagePath);
// Append it to the formdata using fs.createReadStream
const formData = new FormData();
formData.append('file', fs.createReadStream(savedImagePath));
// Send formData to api and image gets saved correctly
await fetch('TrelloUrl', { method: 'POST', body: formData })
Now I want to do the same thing but without saving the file locally but by using the image buffer. I've tried the following but I can't seem to make it work:
const fetch = require('node-fetch');
const Jimp = require('jimp');
const FormData = require('form-data');
const stream = require('stream');
// Save file to Buffer
const buffer = await Jimp.read(imagePNGURL).getBufferAsync('image/png');
// Convert buffer to stream
const bufferStream = new stream.PassThrough();
bufferStream.end(buffer);
// Try to append it to the formdata and send it to the api
const formData = new FormData();
formData.append('file', bufferStream); // Results in 400 Bad Request
formData.append('file', bufferStream.read()); // Results in empty image being uploaded
await fetch('TrelloUrl', { method: 'POST', body: formData })
---------
// Also tried to convert the buffer to stream like this:
const { Readable } = require('stream');
const bufferToStream = (buffer) => {
const stream = new Readable();
stream.push(buffer);
stream.push(null);
return stream;
};
formData.append('file', bufferToStream(buffer)); // Results in 400 Bad Request
formData.append('file', bufferToStream(buffer).read(); // Results in empty image being uploaded
How can I convert the buffer correctly to a fs.ReadStream() object so I can send it successfully to the api?
Or are there better ways to approach this?
All help is appreciated.
You can get the stream directly from the url using axios and append to form-data
const axios = require("axios")
const getImageStream = async (url) => {
const response = await axios.get(url, {responseType : "stream"});
if (response.status === 200) {
return response.data
}
}
const formData = new FormData();
formData.append('file', await getImageStream(imagePNGURL) );
set custom filename (set whatever name do you want) and content-type, worked for me
const formData = new FormData();
formData.append('file', bufferStream, {filename: 'photo.png', contentType: 'image/png');
I've been trying to do so for several hours to no success. The relevant API endpoint is block/put. IT asks for the HTTP request to use multipart/form-data, but I'm not sure how to do it. Here is one attempt:
const req = require("xhr-request-promise");
const FormData = require("form-data");
(async () => {
const form = new FormData();
form.append("data", new Buffer([1, 2, 3]));
console.log(await req("https://ipfs.infura.io:5001/api/v0/block/put", {
method: "POST",
body: form
}));
})();
ipfs-http-client is perfect for this task:
const { create } = require('ipfs-http-client');
// connect to ipfs daemon API server
const ipfs = create('https://ipfs.infura.io:5001');
(async () => {
await ipfs.block.put(new Uint8Array([1, 2, 3]));
})();