Uploading file on Hapi.js server - file

I'm trying to upload file on a hapi server, and my goal would be to upload a zip file and unzip it on the server, but I currently have problems withs the upload part for a single file...
my frontend is made with react and I'm selecting a file with a <input>
my route is made like this
method: 'POST',
path: '/upload',
config: {
payload: {
maxBytes: 209715200,
output: 'stream',
parse: true
},
handler: handlers.uploadFile,
description: 'upload file'
}
});
I used a stream type output, but I can't figure out what is the type to used depending on the situation between stream, data, or file.
Here my handler uploadfile() is this one :
handler.uploadFile = async (req, h) => {
var doc = req.payload
return true;
}
But I can't get any informations on my file like doc.name or doc._hapi.name so I don't really know how to use the data here.
If someone know a site where all of this is explain, or could help me on that that would help a lot !
Thanks !

Ok so I just figure out what the problem was.
I needed to pass my data as a formData from my react component like that
var formData = new FormData();
formData.append("file", data)
if anyone have the same problem, that is a solution I suppose

Related

React-Flask download excel file with button click

I'm trying to download an excel file with the click of a button in my web application. I can see the data come across from my api request, but when I download the file and try to open it I either get a:
"We found a problem with some content in ... Do you want us to try to recover as much as possible" YES => "This file is corrupt and cannot be opened"
or
"... the file format or file extension is not valid. Verify that theh file has not been corrupted..."
If I open the original file saved it works fine so it's not the file. I think the problem is somewhere in the React Code.
I've looked at a lot of other questions on Stack Overflow about this same topic but none of the answers seem to be working for me.
React
React.useEffect(() => {
if (template && downloadBtn.current != null) {
axios
.get<Blob>(
`/template`,
{ params: { filename: template } }
// responseType: 'blob' or "arraybuffer" don't work for me
)
.then((resp) => {
console.log(resp.data);
var blob = new Blob([resp.data], {
type: resp.headers['content-type'] // tried keeping and removing this
}); // removing this assuming resp.data is already a blob didn't work
console.log(blob); // PK ... b���C���h����ؒ )���G+N�
const url = window.URL.createObjectURL(blob);
console.log(url); // blob:http://localhost:3000/29fd5f64-da6a-4b9c-b4a4-76cce1d691c8
if (downloadBtn.current != null) {
downloadBtn.current.download = template;
downloadBtn.current.href = url;
}
});
}
}, [template, downloadBtn.current]);
Flask
#app.route('/template', methods=['GET'])
def template():
filename = getRouteData(['filename']) # helper function I wrote to get request.body data
print(os.path.join(
app.config['templates_folder'], filename), file=sys.stderr)
return send_file(os.path.join(app.config['templates_folder'], filename))
# adding as_attachment=True doesn't work for me either
# file path is correct

Upload react-pdf dynamically generated file to Sanity using NextJS

I'm working on an e-commerce app built on NextJS and Sanity, so far I've made some mock products with all the necessary requirements, a user login system and checkout. I've been trying to make an invoice system so that when the user confirms an order 3 things must happen:
send all the order data to a react-pdf component and generate the invoice(working)
post the invoice file to the sanity schema so that the user has access to it when he goes to his order history page(not working)
email both the company and the client about the order(not implemented yet but I can do it)
ReactPDF allows me to access the pdf through a hook that returns me the blob of the file and the URL. I've tried to POST both of them but the url returned 404 and the blob didn't upload at all.
Searched the docs of both ReactPDF and Sanity and I couldn't find anything, although I think it has to do something with this endpoint from Sanity:
myProjectId.api.sanity.io/v2021-06-07/assets/files/myDataset
This is how I POST the order to my sanity studio
const { data } = await axios.post(
'/api/orders',
{
user: userInfo,
invoice_id: orders.length + 1,
orderItems: cartItems.map((item) => ({
...item,
slug: undefined
})),
billingData,
paymentMethod,
itemsPrice,
taxPrice,
totalPrice
},
{
headers: {
authorization: `Bearer ${userInfo.token}`
}
}
);
I've tried making 2 POST requests, one for the invoice_file alone, trying to post the blob or the url but none did work. The schema for invoice file was updated for the type of post each time so I'm 99% sure that wasn't the issue, anyway here's how the schema for invoice_file looks as for file:
{
name: 'invoice_file',
title: 'Invoice',
type: 'file',
options: {
storeOriginalFilename: true
}
},
If there would be any other code snippets relevant please let me know.
I really don't know how to find the solution for this as it's the first time trying to do such thing, so help would be much appreciated.
Thanks in advance!
I apologies as I'm not really active here but it's hard to pass on your question especially as I'm working on something similar. There's probably other ways to do this but I suggest you work use the official Sanity client. There's a specific section in the README that tells us how to do the file uploads or here.
So here's kinda the very small snippet:
import {
Document,
pdf,
} from "#react-pdf/renderer";
const doc = <Document />;
const asPdf = pdf([]); // {} is important, throws without an argument
asPdf.updateContainer(doc);
const blob = await asPdf.toBlob();
// `blob` here is coming from your react-pdf blob
const fileName = "customfilename.pdf";
client.assets.upload("file", blob, { filename: fileName }).then((fileAsset) => {
console.log(fileAsset", fileAsset);
// you can then use the fileAsset to set and reference the file that we just uploaded to our document
client.patch("document-id-here").set({
invoice_file: {
_type: "file",
asset: {
_type: "reference",
_ref: fileAsset._id,
},
},
}).commit();
});

upload image to S3 presigned url using react-native-image-picker and axios

I am trying to get an presigned url image upload working correctly. Currently the upload succeeds when selecting an image from the IOS simulator, however when I actually try to view the file it seems the file is corrupted and will not open as an image. I suspect it has something to do with my FormData but not sure.
export async function receiptUpload(file) {
const date = new Date();
const headers = await getAWSHeaders();
const presignUrl = await request.post(
urls.fileUpload.presignUpload,
{file_name: `${date.getTime()}.jpg`},
{headers}
)
.then(res => res.data);
const formData = new FormData();
formData.append('file', {
name: `${date.getTime()}.jpg`,
uri: file.uri,
type: file.type
});
const fileUpload = presignUrl.presignUrl && await request.put(
presignUrl.presignUrl,
formData
)
.then(res => res.status === 200);
}
I have tried from other fixes to change the file uri like so...
Platform.OS === 'android' ? file.uri : file.uri.replace('file://', '');
however this does not seem to work either.
I did this just recently in my current project and the following code is a working example for my use case. I didn't need to convert to a blob either though I am uploading to AWS S3 so if you are uploading elsewhere that may be the issue.
export const uploadMedia = async (fileData, s3Data, setUploadProgress = () => {}) => {
let sendData = { ...fileData };
sendData.data.type = sendData.type;
let formData = new FormData();
formData.append('key', s3Data.s3Key);
formData.append('Content-Type', fileData.type);
formData.append('AWSAccessKeyId', s3Data.awsAccessKey);
formData.append('acl', 'public-read');
formData.append('policy', s3Data.s3Policy);
formData.append('signature', s3Data.s3Signature);
formData.append('file', sendData.data);
return axios({
method: 'POST',
url: `https://${s3Data.s3Bucket}.s3.amazonaws.com/`,
data: formData,
onUploadProgress: progressEvent => {
let percentCompleted = Math.floor((progressEvent.loaded * 100) / progressEvent.total)
setUploadProgress(percentCompleted);
}
})
}
I would first check to see where the issue is occurring. After uploading can you view it on whatever storage service you are trying to upload it to. If so it's something on React Native side. If it doesn't ever get uploaded to the location you know its an error in your upload process. Might help you track the exact location of the error.
I had to do this recently for a project. I believe the data is a base64 string when coming directly from the file input. So the issue is your are uploading a base64 string not the image by simply passing the data field. I had to process it before uploading to the signed URL with the following method.
private dataUriToBlob(dataUri) {
const binary = atob(dataUri.split(',')[1]);
const array = [];
for (let i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], { type: 'image/jpeg' });
}
This answer fixed it for me: How can I upload image directly on Amazon S3 in React Native?
I had tried uploading with axios and fetch with FormData. The download went through but the image file was not readable, even when downloaded to my Mac from the S3 console:
The file "yourfile.jpg" could not be opened. It may be damaged or use a file format that Preview doesn’t recognize.
Only after trying to upload with XHR with the correct Content-Type header did it work. Your signedUrl should be correct as well, which seems to be the case if the download goes through.

upload multiple epub/zip files on cloudinary [reactjs]

when i try and upload epub file , i get respone
{"error":{"message":"Unsupported ZIP file"}}
what am i doing wrong here:
const formData=new FormData();
formData.append("resource_type", "auto");
formData.append("file", file);
formData.append("upload_preset", config.upload_preset);
formData.append("api_key", config.api_key);
formData.append("timestamp", (Date.now() /1000) |0);
await axios.post(cloudinaryUploadUrl, formData, {
headers: { "X-Requested-With":"XMLHttpRequest",},
}).then(response => {
constdata=response.data;
gUrl=gUrl.concat([data.secure_url]);
})
update , i was using wrong url to upload raw files
I was using link :
'https://api.cloudinary.com/v1_1//image/upload'
instead of
'https://api.cloudinary.com/v1_1//raw/upload'
hence the issue is solved 😅
You can take a look at the supported file types here- https://cloudinary.com/documentation/image_transformations#image_format_support
We are checking this issue with the team and will update you with any insights.

React dropzone, how to upload image?

Using React dropzone, I've successfully accessed the image using the onDrop callback. However, I'm trying to upload to Amazon S3 by sending the image to my server, saving to an S3 bucket, and returning a signed url to the image back to the client.
I can't do this with the information I have so far and the docs don't seem to mention this to my knowledge.
onDrop triggers a function call in my redux actions with the files:
export function saveImageToS3 (files, user) {
file = files[0]
// file.name -> filename.png
// file -> the entire file object
// filepreview -> blob:http:localhost:3000/1ds3-sdfw2-23as2
return {
[CALL_API] : {
method:'post',
path: '/api/image',
successType: A.SAVE_IMAGE,
body: {
name: file.name,
file: file,
preview: file.preview,
username: user
}
}
}
}
However, when I get to my server, I'm not sure how to save this blob image (that's only referenced from the browser.)
server.post('/api/image', (req, res) => {
// req.body.preview --> blob:http://localhost:3000/1ds3-sdfw2-23as2
// req.body.file -> {preview:blob:http://localhost:3000/1ds3-sdfw2-23as2}, no other properties for some reason
})
React Dropzone returns an array of File objects which can be sent to a server with a multi-part request. Depend on the library you use it can be done differently.
Using Fetch API it looks as follows:
var formData = new FormData();
formData.append('file', files[0]);
fetch('http://server.com/api/upload', {
method: 'POST',
body: formData
})
Using Superagent you would do something like:
var req = request.post('/api/upload');
req.attach(file.name, files[0]);
req.end(callback);

Resources