How to Save Image in server - reactjs

I am trying to save an image in database but when I do the following it saves with dataURL, but that URL starts with localhost, how can I prevent it? I used React for frontend.
uploadImage = (event) => {
var imgSize = event.target.files[0].size;
$('#img').attr('hidden', false);
if (imgSize < 1000000 ) {
this.setState({
image: URL.createObjectURL(event.target.files[0]),
imageSize: imgSize
});
document.getElementById("errImgUpload").innerHTML = "";
}
else {
document.getElementById("errImgUpload").innerHTML = "Maximum image size 1Mb";
}
}
<div className="form-group">
<label for="file-upload" className="custom-file-upload">
<span className="fa fa-upload"></span> Upload image
</label>
<input onChange={(event) => this.uploadImage(event)} name="file-upload" id="file-upload" type="file" accept="image/*" />
<span id="errImgUpload" className="text text-danger"></span>
</div>
The Blob is http://localhost:10002/b46e96f5-83ce-4d10-b668-2bd038721b5a, what is a blob?

URL.createObjectURL() creates a blob which is a binary representation of the file in the memory. It doesn't upload the file. I am not sure from where you got the code. You may want to read more about this at MDN.
Uploading requires a backend service to open an endpoint for you to send post data to. You need to use <input type='file'> tag to send the file as form data and set the service endpoint as the url in the form. Start with this article.

You need to post your image data with FormData, like this:
const formData = new FormData();
formData.append('image', files[0]);
fetch(url, {
method: 'POST',
body: data
}).then(...);
And blob is Binary Large Object, more detail you can find in MDN.

Related

Which HTTP Method to Use with Forms?

My web app information:
Frontend: React.js
Backend: Flask
Goal: User enters in zip codes and the backend returns the zip code coordinates and distance on the web page
Problem: I was initially under the impression that you only use POST requests when inserting into a database, so I was defining my API endpoints as GET methods. However, since I am under the assumption that it is best to not pass body parameters for GET methods, my current solution is to have it as a POST request. Is this the best practice? Or is there a better way to do it?
Frontend Code
const handleSubmit = e => {
const formData = { "origin": originInput, "destination": destinationInput
}
e.preventDefault();
checkError();
fetch('/path', {
credentials: 'include',
method: 'POST',
body: JSON.stringify(formData),
headers: { 'content-type': 'application/json' }
}).then(res => console.log(res))
.catch(err => console.log(err));
};
return (
<div className="card">
<form onSubmit={handleSubmit}>
<section>
<label htmlFor="origin">Start Zip</label>
<input
type="text"
name="origin"
id="origin"
onChange={e => handleChange(e, updateOriginInput)}
/>
</section>
<section>
<label htmlFor="destination">End Zip</label>
<input
type="text"
name="destination"
id="destination"
onChange={e => handleChange(e, updateDestinationInput)}
/>
</section>
<section>
<input type="submit" value="Get Directions" />
</section>
</form>
</div>
);
Backend Code
#path.route('/path', methods=['POST'])
def path_info():
request_data = request.get_json()
ORIGIN = request_data['origin']
DESTINATION = request_data['destination']
# The df var is pd.DataFrame(zip([ORIGIN, get_lon(ORIGIN), get_lat(ORIGIN)], [DESTINATION, get_lon(DESTINATION), get_lat(DESTINATION)])).T
df, MILES = preprocess(ORIGIN, DESTINATION)
print(df)
return {
'origin': {
'longitude': df['LON'][0],
'latitude': df['LAT'][0]
},
'destination': {
'longitude': df['LON'][1],
'latitude': df['LAT'][1]
},
'miles': MILES
}
Thanks in advance!
I was initially under the impression that you only use POST requests when inserting into a database, so I was defining my API endpoints as GET methods. However, since I am under the assumption that it is best to not pass body parameters for GET methods, my current solution is to have it as a POST request. Is this the best practice? Or is there a better way to do it?
Today: if you need to send information in the body of the HTTP request, then you should expect to use POST (with PUT/PATCH available in specific cases).
If you want to instead use GET, then you need to take the information collected by the form and figure out how to encode it into the request URI itself. On the web, that usually takes the form of key value pairs that have been application/x-www-form-urlcoded and copied into the query part of the request URI. It doesn't have to be in the query part - URI Templates can be used to describe the expansion of URI paths as well.
There is an internet draft to standardize a new HTTP method (QUERY) which would provide semantics for a safe request with a message body; but that method hasn't been standardized or registered yet.

How to upload a file using Gin + React?

I want to upload a image file from React, doing so seems I need to store the image on the server and retrieve it from a POST request in order to modify it into a url path.
Using Gin Gonic http framework.
Here is the form in React for my POST request:
<form action="/upload" method="POST">
<label htmlFor="upload" onChange={onChange}>
<FontAwesomeIcon icon={faUserCircle} color="#3B5998" size="10x" className={`${pointer}`} />
<input type="file" hidden id="upload" name="upload" />
</label>
</form>
Here is my method I am calling in an onChange to send the request along with the image file:
uploadFile = (file) => {
const formData = new FormData();
formData.append('image', file);
axios({
method: 'post',
url: `${gamingApiBaseURL}/v1/upload-image`,
data: formData,
headers: { 'Content-Type': 'multipart/form-data' },
}).catch((error) => {
console.log('error storing image', error);
});
};
Here is my Go struct in order to bind the request
type ImageForm struct {
Image *multipart.FileHeader `form:"upload binding:"required"`
}
Lastly, the method that is supposed to get the image file and upload it to the server. Here is what I have so far. I am receiving an error saying http: no such file which is weird because in Postman I see the image key and the filename, I'm trying to make sense of how uploading an image works in Go.
func extractImage(c *gin.Context) {
// Using 'ShouldBind'
formFile, err := c.FormFile("image")
fmt.Println("Error", err)
if err != nil {
c.JSON(http.StatusBadRequest, err)
}
fmt.Println("form error", formFile)
}
I think this struct tag is wrong
type ImageForm struct {
Image *multipart.FileHeader `form:"upload binding:"required"`
}
Change to this (missing double quote after upload):
type ImageForm struct {
Image *multipart.FileHeader `form:"upload" binding:"required"`
}

How to reduce image size in multi-part FormData file upload

html
<form #form enctype="multipart/form-data">
<input type="file" #upload name='uploadingFiles' (change)="uploadFiles(form)" multiple>
</form>
Angular
void uploadFiles(form) {
var formData = new FormData(form);
final request = new HttpRequest();
request.open('POST', 'http://localhost:8080/uploadMulti');
request.upload.onProgress.listen((ProgressEvent e) {
print('progress');
});
request.onLoad.listen((e) {
print('Uploaded');
});
request.send(formData);
}
How can I put image manipulation code here to reduce an image that is 4000X4000 to 600X600 and then replace it in the formData before sending ? Is it possible or is the formData just meta-data passed to the server and then server uses that to pull image bytes one file at a time ?
Angular has a good package to make a compression on the image before you upload it to your server.
you can use this https://www.npmjs.com/package/ngx-image-compress
and here is a good article if you have doubts about who you can do it.
https://medium.com/swlh/compress-image-and-send-it-to-an-api-in-angular-bc48e6ed3835

Unable to send attachment with the email using reactjs

I'm new to react, my objective is to send attachment with the email. For emailing purpose, we're using sendgrid and for uploading files or attachments we're sendgrid mail helper attachment in backend. But i couldn't able to upload file, i can send only email but i couldn't able to send email with attachment. I couldn't able to figure it out where i'm going wrong. I have been struggling from couple of weeks but couldn't figure out where i'm going wrong.
Here is the code:
fileChange = e => {
this.setState(
{ file: e.target.files[0], fileName: e.target.files[0].name },
() => {
console.log(
"File chosen --->",
this.state.file,
console.log("File name --->", this.state.fileName)
);
}
);
};
<Button.Content hidden>Choose a File</Button.Content>
</Button>
<input
type="file"
id="file"
hidden
onChange={this.fileChange}
/>
<Form.Input
fluid
label="File Chosen: "
placeholder="browse your file system"
readOnly
value={this.state.fileName}
/>
Can anyone help me in this query please?
you are passing file but you set wrong content-type.
headers: { 'Content-Type': 'application/json' }
Please use the following line instead above line
headers: {"Content-Type": "multipart/form-data"}

How to display mysql image in angularjs? (AngularJs -> Node.js -> abc.com -> mysql)

I am hosting a website on Heroku with Node.js and AngularJs but my database is somewhere else (say abc.com).
I want to store image in mysql database at abc.com (Not saving images on heroku).
I have used text, blob, longblob datatype to store image from AngularJs using ng-file-upload (npm module). When i upload image, it is stored in database.
I have created a rest api on abc.com to fetch database values and consuming rest in node.js.
Now, I want to fetch image from database and display in html page. I have fetched database value from mysql -> abc.com -> node.js -> angularjs and tried angular-base64, atob and btoa to convert database value to show image, but i had no luck.
let _arrayBufferToBase64 = function (buffer) {
return $base64.encode(buffer);
};
let _arrayBufferToBase64 = function (buffer) {
console.log('_arrayBufferToBase64')
var binary = '';
var bytes = new Uint8Array(new Buffer(buffer, 'base64'));
// var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
console.log(len);
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
};
UtilService.fetchImage()
.then(function(res){
console.log(res);
if(res.success){
let data = res.data[0].profile_pic;
console.log(data);
$scope.img = 'data:image/png;base64,'+_arrayBufferToBase64(data);
// $scope.img = 'data:image/png;base64,'+data;
console.log($scope.img);
} else {
console.log('image not found');
$scope.alt = "Image is not found";
}
})
}
template: '<img class="img-responsive img-hover" ng-src={{img}} alt={{alt}}"/>'
When my database was in heroku, above code was working fine. But now i need some help.
Thanks in advance...
Found solution for my question and want to share with others.
My requirement was to send image from angularjs to nodejs, and from nodejs to abc.com (where my database is present).
From angularjs, I used ng-file-upload as:
<div class="col-sm-12">
<button class="col button btn btn-primary btn-sm" ng-model="$ctrl.imageFile" id="imageFile" name="imageFile" ngf-pattern="'image/*'" ngf-select ngf-accept="'image/*'" ngf-max-size="2MB" ngf-resize="{width: 512, height: 512, quality: 1}">Select/Change</button>
<p class="text-danger text-center" ng-show="profileImageForm.imageFile.$error.maxSize">
2MB is max size
</p>
<p class="text-danger text-center" ng-show="profileImageForm.imageFile.$error.pattern">
Select image
</p>
<button ng-show="!!$ctrl.imageFile" class="col btn btn-primary btn-sm" ng-click="$ctrl.uploadProfilePic($ctrl.imageFile)">Upload</button>
</div>
Upload.upload({
// request method is post
url: 'server-url',
data: { imageFile: $ctrl.imageFile },
headers: Utility.authHeader
}).then(function (resp) {
// ...
})
On server side (NodeJs):
app.post('server-url', , function (req, res) {
const formidable = require('formidable');
const form = new formidable.IncomingForm();
const base64Img = require('base64-img');
form.encoding = 'utf-8';
form.parse(req, function (err, fields, file) {
logger.debug(file);
if (!!file.imageFile && !!file.imageFile.path) {
const uploadedImagePath = file.imageFile.path // imageFile is form param name
logger.debug(uploadedImagePath); // image will be stored in temp folder on server
// convert image to base64 encoded string
base64Img.base64(uploadedImagePath, function (err, base64String) {
logger.debug(base64String);
// send base64String to abc.com and store in database
});
} else {
logger.debug("Image path is not available");
res.json({ success: false })
}
});
})
When i want to display stored image:
Fetch base64String from database and use as if it is image:
Utility.fetchImage()
.then(function(res){
$ctrl.img = res.data;
})
<img class="img-responsive img-hover" ng-src={{img}} />
I hope it will help you. I would be happy to know other alternatives as well.

Resources