I build an app use vue and codeigniter rest server, I try to upload file by postman and it's work fine, but when I try from front-end, file is not uploaded, folder permission has been allowed, this is my vue code
data() {
return {
data: {
photo: // base64 data
}
}
}
on methods
addMember(){
this.axios.post('member', this.data).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
}
on back end
$filename = round(microtime(true)).'.png';
$config['file_name'] = $filename;
$config['upload_path'] = './storage/';
$config['allowed_types'] = '*';
$config['max_size'] = 50000;
$config['max_width'] = 50000;
$config['max_height'] = 50000;
$this->load->library('upload', $config);
$this->upload->do_upload('photo');
thanks for your response
I think if you success get the send but without file, maybe your send type has error
For server Base64 is a String ,not a file(byte stream) ,for axios ,default send type is Application/json, and it only can not send a Byte Stream , so you should cheack your server can get a String and transform to file
But if your server want a file , you should use formData
And I suggest you use FormData to send file
Here is a examples for you if you want use axios send formData.
let formData = new FormData();
formData.append(photo,this.photo);
this.$axios({
url: '/member',
method: 'post',
data: formData
});
Related
My model is held in a JavaScript object on the client side, where the user can edit its properties via the UI controls. I want to offer the user an option to download a JSON file representing the model they're editing. I'm using MVC core with .net 6.
What I've tried
Action method (using Newtonsoft.Json to serialize the model to JSON):
public IActionResult Download([FromForm]SomeModel someModel)
{
var json = JsonConvert.SerializeObject(someModel);
var characters = json.ToCharArray();
var bytes = new byte[characters.Length];
for (var i = 0; i < characters.Length; i++)
{
bytes[i] = (byte)characters[i];
}
var stream = new MemoryStream();
stream.Write(bytes);
stream.Position = 0;
return this.File(stream, "APPLICATION/octet-stream", "someFile.json");
}
Code in the view to call this method:
<button class="btn btn-primary" onclick="download()">Download</button>
And the event handler for this button (using jQuery's ajax magic):
function download() {
$.ajax({
url: 'https://hostname/ControllerName/Download',
method: 'POST',
data: { someModel: someModel },
success: function (data) {
console.log('downloading', data);
},
});
}
What happened
The browser console shows that my model has been posted to the server, serialized to JSON and the JSON has been returned to the browser. However no file is downloaded.
Something else I tried
I also tried a link like this to call the action method:
#Html.ActionLink("Download", "Download", "ControllerName")
What happened
This time a file was downloaded, however, because ActionLink can only make GET requests, which have no request body, the user's model isn't passed to the server and instead the file which is downloaded represents a default instance of SomeModel.
The ask
So I know I can post my model to the server, serialize it to JSON and return that JSON to the client, and I know I can get the browser to download a JSON-serialized version of a model, but how can I do both in the same request?
Edit: What I've done with the answer
I've accepted Xinran Shen's answer, because it works as-is, but because I believe that just copying code from Stack Overflow without understanding what it does or why isn't good practice, I did a bit of digging and my version of the saveData function now looks like this:
function saveData(data, fileName) {
// Convert the data to a JSON string and store it in a blob, a file-like
// object which can be downloaded without it existing on the server.
// See https://developer.mozilla.org/en-US/docs/Web/API/Blob
var json = JSON.stringify(data);
var blob = new Blob([json], { type: "octet/stream" });
// Create a URL from which the blob can be downloaded - see
// https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
var url = window.URL.createObjectURL(blob);
// Add a hidden hyperlink to the page, which will download the file when clicked
var a = document.createElement("a");
a.style = "display: none";
a.href = url;
a.download = fileName;
document.body.appendChild(a);
// Trigger the click event on the hyperlink to download the file
a.click();
// Release the blob's URL.
// Browsers do this when the page is unloaded, but it's good practice to
// do so as soon as it's no longer needed.
window.URL.revokeObjectURL(url);
// Remove the hidden hyperlink from the page
a.remove();
}
Hope someone finds this useful
First, Your code is right, You can try to access this method without ajax, You will find it can download file successfully,But You can't use ajax to achieve this, because JavaScript cannot interact with disk, you need to use Blob to save the file. change your javascript like this:
function download() {
$.ajax({
url: 'https://hostname/ControllerName/Download',
method: 'Post',
data: { someModel: someModel },,
success: function (data) {
fileName = "my-download.json";
saveData(data,fileName)
},
});
}
var saveData = (function () {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return function (data, fileName) {
var json = JSON.stringify(data),
blob = new Blob([json], {type: "octet/stream"}),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
};
}());
I think you may need FileStreamResult, also you need to set the MIME type to text file or json file.
// instead of this
return this.File(stream, "APPLICATION/octet-stream", "someFile.json");
// try this
return new FileStreamResult(stream, new MediaTypeHeaderValue("text/plain"))
{
FileDownloadName = "someFile.txt"
};
// or
return new FileStreamResult(stream, new MediaTypeHeaderValue("application/json"))
{
FileDownloadName = "someFile.json"
};
Reference: https://www.c-sharpcorner.com/article/fileresult-in-asp-net-core-mvc2/
I am sending blob PDF generated by JSPDF to Laravel API from the front end, but Laravel doesn't seeing it and saying the the field is required, when I console.log() the blob I see that it exists as bellow
Blob
size: 2888211
type: "application/pdf"
[[Prototype]]: Blob
the code in Laravel to store it
$report = $request->file('report');
$ext = $report->getClientOriginalExtension();
$report_name = $request->qr_url . ".$ext";
$report->move(public_path('uploads/reports/'), $report_name);
What is the wrong here please?
Why ?
just send them as files
let reader = new FileReader();
reader.addEventListener('load', (event) => {
// send that file
let file = event.target.result;
let formData = new FormData();
formData.append('file', file);
let request = new XMLHttpRequest();
request.open("POST", "endpoint url");
request.send(formData);
});
reader.readAsDataURL(blob);
I created a script that extracts photos in the gallery of a certain profile…
Using instagram-web-api
Unfortunately now it no longer works, instagram does not return the image of the media
This is the mistake:
ERR_BLOCKED_BY_RESPONSE
Instagram has changed it’s CORS policy recently? How I can fix?
for php; I changed my img src to this and it works like charm! Assume that $image is the instagram image cdn link came from instagram page:
'data:image/jpg;base64,'.base64_encode(file_get_contents($image))
EDIT FOR BETTER SOLUTION
I have also noticed that, this method is causing so much latency. So I have changed my approach and now using a proxy php file (also mentioned on somewhere on stackoverflow but I don't remember where it is)
This is my common proxy file content:
<?php
function ends_with( $haystack, $needle ) {
return substr($haystack, -strlen($needle))===$needle;
}
if (!in_array(ini_get('allow_url_fopen'), [1, 'on', 'true'])) {
die('PHP configuration change is required for image proxy: allow_url_fopen setting must be enabled!');
}
$url = isset($_GET['url']) ? $_GET['url'] : null;
if (!$url || substr($url, 0, 4) != 'http') {
die('Please, provide correct URL');
}
$parsed = parse_url($url);
if ((!ends_with($parsed['host'], 'cdninstagram.com') && !ends_with($parsed['host'], 'fbcdn.net')) || !ends_with($parsed['path'], 'jpg')) {
die('Please, provide correct URL');
}
// instagram only has jpeg images for now..
header("Content-type: image/jpeg");
readfile( $url );
?>
Then I have just converted all my instagram image links to this (also don't forget to use urlencode function on image links):
./proxyFile.php?url=https://www.....
It worked like charm and there is no latency anymore.
now 100% working.
You can try this.
corsDown
Using the Google translation vulnerability, it can display any image URL, with or without permission. All these processes are done by the visitor's IP and computer.
I have the same problem, when I try to load a Instagram's pictures url (I tried with 3 IP addresses), I see this on the console:
Failed to load resource: net::ERR_BLOCKED_BY_RESPONSE
You can see it here, the Instagram image doesn't load (Actually, when I paste this url on google it works, but Instagram puts a timestamp on there pictures so, it's possible it won't work for you).
It's very recent, 3 days ago, it works with no issues.
<img src="https://scontent-cdt1-1.cdninstagram.com/v/t51.2885-19/s320x320/176283370_363930668352575_6367243109377325650_n.jpg?tp=1&_nc_ht=scontent-cdt1-1.cdninstagram.com&_nc_ohc=nC7FG1NNChYAX8wSL7_&edm=ABfd0MgBAAAA&ccb=7-4&oh=696d56547f87894c64f26613c9e44369&oe=60AF5A34&_nc_sid=7bff83">
The answer is as follows. You can use the imgproxy.php file. You can do it like this:
echo '<a href="' . $item->link . '" class="image" target="_blank">
<span style="background-image:url(imgproxy.php?url=' . urlencode($thumbnail) . ');"> </span>
</a>';
Using PHP
u can grab content of the image and show it in php file as an image by setting the header:
<?php
$img_ctn = file_get_contents("https://scontent-ber1-1.cdninstagram.com/v/......");
header('Content-type: image/png');
echo $img_ctn;
You can display the Image using Base64 encoded.
Base64 func based on #abubakar-ahmad answer.
JavaScript:
export const checkUserNameAndImage = (userName) => {
/* CALL THE API */
return new Promise((resolve, reject) => {
fetch(`/instagram`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ userName }),
})
.then(function (response) {
return response.text();
})
/* GET RES */
.then(function (data) {
const dataObject = JSON.parse(data);
/* CALL BASE64 FUCNTION */
toDataUrl(dataObject.pic, function (myBase64) {
/* INSERT TO THE OBEJECT BASE64 PROPERTY */
dataObject.picBase64 = myBase64;
/* RETURN THE OBJECT */
resolve(dataObject);
});
})
.catch(function (err) {
reject(err);
});
});
};
Base64 func:
function toDataUrl(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function () {
var reader = new FileReader();
reader.onloadend = function () {
callback(reader.result);
};
reader.readAsDataURL(xhr.response);
};
xhr.open("GET", url);
xhr.responseType = "blob";
xhr.send();
}
Now, instead of using the original URL, use the picBase64 property:
<image src={data.picBase64)}/>
I have built a simple PHP based media proxy to minimize copy&paste.
https://github.com/skmachine/instagram-php-scraper#media-proxy-solving-cors-issue-neterr_blocked_by_response
Create mediaproxy.php file in web server public folder and pass instagram image urls to it.
<?php
use InstagramScraper\MediaProxy;
// use allowedReferersRegex to restrict other websites hotlinking images from your website
$proxy = new MediaProxy(['allowedReferersRegex' => "/(yourwebsite\.com|anotherallowedwebsite\.com)$/"]);
$proxy->handle($_GET, $_SERVER);
I was too lazy to do the suggested solutions and since i had a nodejs server sending me urls i just wrote new functions to get the images, convered them to base64 and sent them to my frontend. Yes it's slower and heavier but it gets the job done for me since i don't have a huge need for performance.
Fetch and return base64 from url snippet
const getBase64Image = async (url) => {
return new Promise((resolve, reject) => {
// Safety net so the entire up
// doesn't fucking crash
if (!url) {
resolve(null);
}
https
.get(url, (resp) => {
resp.setEncoding("base64");
body = "data:" + resp.headers["content-type"] + ";base64,";
resp.on("data", (data) => {
body += data;
});
resp.on("end", () => {
resolve(body);
});
})
.on("error", (e) => {
reject(e.message);
});
});
};
You don't need any external modules for this.
I am fairly new to coding and I'm in the learning phase for both React Native and Laravel. I was working on some practice project and I needed to upload an image from my React Native app to the Laravel server and from the server I could save it on a cloud or something. I can upload and display the image on the app using expo-image-picker but I just can't seem to get it to post it to the server using formData.
Also, why is that when I console.log formData why is it showing an empty object?
My code to loading the image and uploading it:
pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log(result);
if(!result.cancelled)
{
this.setState({
image : result.uri
})
}
// ImagePicker saves the taken photo to disk and returns a local URI to it
let localUri = result.uri;
//console.log("localUri:", localUri)
let filename = localUri.split('/').pop();
console.log("filename:", filename)
// extract the filetype
//let fileType = localUri.substring(localUri.lastIndexOf(".") + 1);
//console.log(fileType)
let fileType = localUri.substring(localUri.lastIndexOf(":") + 1,localUri.lastIndexOf(";")).split("/").pop();
console.log("type:", fileType)
let formData = new FormData();
formData.append("photo", {
uri : localUri,
name: `photo.${fileType}`,
type: `image/${fileType}`
});
console.log("formdata", formData)
let options = {
method: "POST",
body: formData,
headers: {
Accept: "application/json",
"Content-Type": "multipart/form-data"
}
};
let response = await fetch(`${this.props.url}imagetest`, options)
result = await response.json()
console.log(result)
My simple code for api.php in Laravel is:
Route::post("/imagetest", function (Request $request) {
return ["uploaded" => $request->hasFile("photo")];
});
Found the solution at
send image using Expo
The problem I was having, I was testing it by running the code on web, when I ran it on the device I could see the formdata as well as the image was been uploaded too
I am trying to get my file upload functionality done using Angular2 and SpringBoot. I can certify that my java code for the file uploading working fine since I have tested it successfully using Postman.
However, when it comes to sending the file from Angular2 front end, I am getting the HTTP 400 response saying Required request part 'file' is not present.
This is how I send the POST request from Angular2.
savePhoto(photoToSave: File) {
let formData: FormData = new FormData();
formData.append('file', photoToSave);
// this will be used to add headers to the requests conditionally later using Custom Request Options
this._globals.setRequestFrom("save-photo");
let savedPath = this._http
.post(this._endpointUrl + "save-photo", formData)
.map(
res => {
return res.json();
}
)
.catch(handleError);
return savedPath;
}
Note that I have written a CustomRequestOptions class which extends BaseRequestOptions in order to append Authorization header and Content Type header. Content Type header will be added conditionally.
Following is the code for that.
#Injectable()
export class CustomRequestOptions extends BaseRequestOptions {
constructor(private _globals: Globals) {
super();
this.headers.set('X-Requested-By', 'Angular 2');
this.headers.append('virglk', "vigamage");
}
merge(options?: RequestOptionsArgs): RequestOptions {
var newOptions = super.merge(options);
let hdr = this._globals.getAuthorization();
newOptions.headers.set("Authorization", hdr);
if(this._globals.getRequestFrom() != "save-photo"){
newOptions.headers.set('Content-Type', 'application/json');
}else{
//request coming from save photo
console.log("request coming from save photo");
}
return newOptions;
}
}
This conditional header appending is working fine. The purpose of doing that is if I add 'Content-Type', 'application/json' header to every request, file upload method in Spring controller will not accept it. (Returns http 415)
Everything seems to be fine. But I get Required request part 'file' is not present error response. Why is that? I am adding that param to the form Data.
let formData: FormData = new FormData();
formData.append('file', photoToSave);
This is the Spring Controller method for your reference.
#RequestMapping(method = RequestMethod.POST, value = "/tender/save-new/save-photo", consumes = {"multipart/form-data"})
public ResponseEntity<?> uploadPhoto(#RequestParam("file") MultipartFile file){
if (file.isEmpty()) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setMessage("DEBUG: Attached file is empty");
return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.NOT_FOUND);
}
String returnPath = null;
try {
// upload stuff
} catch (IOException e) {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setMessage(e.getMessage());
return new ResponseEntity<ErrorResponse> (errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<String>(returnPath, HttpStatus.OK);
}
EDIT - Adding the payload of the request captured by the browser
As you can see, the param "file" is available there.
Try to add
headers: {
'Content-Type': 'multipart/form-data'
},
to your
.post(this._endpointUrl + "save-photo", formData)
Change formData.append('file', photoToSave);
to formData.append('file', this.photoToSave, this.photoToSave.name); and also add headers specifying the type of data you are passing to API, in your case it will be 'Content-Type': 'multipart/form-data'. Post the output here if it fails even after changing this.
Is there a chance that you're using zuul in a secondary app that is forwarding the request? I saw this with an update where the headers were stripped while forwarding a multi-part upload. I have a gatekeeper app which forwards requests using zuul to the actual service via a looking from eureka. I fixed it by modifying the url like this:
http://myserver.com/service/upload
to
http://myserver.com/zuul/service/upload
Suddenly the 'file' part of the upload header was no longer stripped away and discarded.
The cause, I suspect was a re-try mechanism which cached requests. On failure, it would re-submit the requests, but somehow for file uploads, it wasn't working properly.
To upload a file to the server, send your file inside a FormData and set content type as multipart/form-data.
export const uploadFile = (url, file, onUploadProgress) => {
let formData = new FormData();
formData.append("file", file);
return axios.post(url, formData, {
headers: {
'Content-Type': 'multipart/form-data;charset=UTF-8',
// other headers
},
onUploadProgress,
})
};
To handle file object, be careful with consumes attribute and #RequestPart annotation here.
#PostMapping(value = "/your-upload-path", consumes = "multipart/form-data")
public ResponseEntity<Object> uploadFile(#RequestPart("file") #Valid #NotNull #NotBlank MultipartFile file) {
// .. your service call or logic here
}