I've tried many examples posted online about uploading images via Nativescript (this part I seem to be getting right bar one or two issues), but my PHP server isn't responding with anything and I don't know how to access the file being uploaded to the server as nowhere in the upload data is the file name mentioned from what I can see. I'm using the background-http plugin, but have a few issues in general, namely:
- Where do I include user data in the image upload to the server using background-http?
- The completed handler on background-http doesn't receive the response from my server, it remains and empty object.
- On the server side, I'm struggling to pick up the file and have no idea how to receive the user data too.
What I'm asking for:
Does anyone have a working example of uploading from Nativescript Core using the Background-http plugin (and submitting user data along with the image), through to the PHP file that will receive it and process it and provide response? For the life of me I can't get it working.
I've tried the Background-http plugin example to the tee, it shows it's uploading but never shows the server response, just shows the responseCode of 200.
On the server side, I have tried many examples I've found online, but none seem to be working - I suspect this is because they are mostly web examples. I need something specific to Nativescript.
Nativescript JS file
exports.uploadImage = () => {
// file path and url
var file = cameraViewModel.imageAsset;
var url = "https://www.wesignit.co.za/api/wsi_1/WSI_1_PROD/image_upload.php";
var name = file.substr(file.lastIndexOf("/") + 1); //this gets the filename
// upload configuration
var bghttp = require("nativescript-background-http");
var session = bghttp.session("image-upload");
var request = {
url: url,
method: "POST",
headers: {
"Content-Type": "application/octet-stream"
},
description: "Uploading file: " + name
};
var task = session.uploadFile(file, request);
task.on("progress", progressHandler);
task.on("error", errorHandler);
task.on("responded", respondedHandler);
task.on("complete", completeHandler);
// event arguments:
// task: Task
// currentBytes: number
// totalBytes: number
function progressHandler(e) {
cameraViewModel.uploadOutputs = "Uploading file: " + name + " - uploaded " + e.currentBytes + " / " + e.totalBytes + "(" + (Math.round(e.currentBytes/e.totalBytes * 100) * 10 / 10) + "%)";
}
// event arguments:
// task: Task
// responseCode: number
// error: java.lang.Exception (Android) / NSError (iOS)
// response: net.gotev.uploadservice.ServerResponse (Android) / NSHTTPURLResponse (iOS)
function errorHandler(e) {
cameraViewModel.uploadOutputs = "received " + e.responseCode + " code.";
//cameraViewModel.uploadOutputs = "Error uploading file - try again!";
//var serverResponse = e.response;
//alert(e.response);
alert("Error uploading file - try again!");
}
// event arguments:
// task: Task
// responseCode: number
// data: string
function respondedHandler(e) {
cameraViewModel.uploadOutputs = "received " + e.responseCode + " code. Server sent: " + e.data;
}
// event arguments:
// task: Task
// responseCode: number
// response: net.gotev.uploadservice.ServerResponse (Android) / NSHTTPURLResponse (iOS)
function completeHandler(e) {
cameraViewModel.uploadOutputs = "received " + e.responseCode + " code";
var serverResponse = e.response;
alert(JSON.stringify(e));
}
}
PHP upload file
header('Content-Type: application/json; charset=utf-8');
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: PUT, GET, POST");
$response = array();
$upload_dir = 'uploads/';
$server_url = 'https://www.wesignit.co.za';
if($_FILES['avatar'])
{
$avatar_name = $_FILES["file"]["name"];
$avatar_tmp_name = $_FILES["file"]["tmp_name"];
$error = $_FILES["file"]["error"];
if($error > 0){
$response = array(
"status" => "error",
"error" => true,
"message" => "Error uploading the file!"
);
}else
{
$random_name = rand(1000,1000000)."-".$avatar_name;
$upload_name = $upload_dir.strtolower($random_name);
$upload_name = preg_replace('/\s+/', '-', $upload_name);
if(move_uploaded_file($avatar_tmp_name , $upload_name)) {
$response = array(
"status" => "success",
"error" => false,
"message" => "File uploaded successfully",
"url" => $server_url."/".$upload_name
);
}else
{
$response = array(
"status" => "error",
"error" => true,
"message" => "Error uploading the file!"
);
}
}
}else{
$response = array(
"status" => "error",
"error" => true,
"message" => "No file was sent!"
);
}
echo json_encode($response);
I expect to see a server response, even if just a dummy response object (which I've also tried), but am only receiving responseStatus, responseCode etc.... The response object which I expect to be populated is empty.
On the server: it's clear that the server is not receiving the file and processing it.
Please help. I'm struggling here. I just need a working example that I can copy going forward.
Related
I developed a PHP project, now I am working on connecting it to react native app. However, I tried many codes to upload image to the server nothing works.
Here is my code example,
const uploadImage = async () => {
// Check if any file is selected or not
if (singleFile != null) {
// If file selected then create FormData
const fileToUpload = singleFile;
const data = new FormData();
data.append('file_attachment', fileToUpload);
// Please change file upload URL
fetch(
'http://192.168.8.105/insaf/mobileConnection/upload.php',
{
method: 'post',
body: data,
headers: {
'Content-Type': 'multipart/form-data; ',
},
}
).then((response) => response.json())
.then((responseJson) => {
//Hide Loader
setLoading(false);
console.log(responseJson);
// If server response message same as Data Matched
if (responseJson[0].Message == "Success") {
navigation.replace('ReqPriceList');
} else {
//setErrortext(responseJson.msg);
console.log('Please check');
}
})
.catch((error) => {
//Hide Loader
setLoading(false);
console.error(error);
});
} else {
// If no file selected the show alert
alert('Please Select File first');
}
};
And for the PHP server side (upload.php), here is the code
if(!empty($_FILES['file_attachment']['name']))
{
$target_dir = "../assets/files/request/";
if (!file_exists($target_dir))
{
mkdir($target_dir, 0777);
}
$target_file =
$target_dir . basename($_FILES["file_attachment"]["name"]);
$imageFileType =
strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if file already exists
if (file_exists($target_file)) {
echo json_encode(
array(
"status" => 0,
"data" => array()
,"msg" => "Sorry, file already exists."
)
);
die();
}
// Check file size
if ($_FILES["file_attachment"]["size"] > 50000000) {
echo json_encode(
array(
"status" => 0,
"data" => array(),
"msg" => "Sorry, your file is too large."
)
);
die();
}
if (
move_uploaded_file(
$_FILES["file_attachment"]["tmp_name"], $target_file
)
) {
echo json_encode(
array(
"status" => 1,
"data" => array(),
"msg" => "The file " .
basename( $_FILES["file_attachment"]["name"]) .
" has been uploaded."));
} else {
echo json_encode(
array(
"status" => 0,
"data" => array(),
"msg" => "Sorry, there was an error uploading your file."
)
);
}
}
I got this code from here https://aboutreact.com/file-uploading-in-react-native/
And I am getting
this error
Can anyone help me?
Any alternative solution will be fine.
Edit:
based on #Sadia Chaudhary code this function works
let uploadImage = async () => {
//Check if any file is selected or not
if (singleFile != null) {
//If file selected then create FormData
const fileToUpload = singleFile;
console.log("fileToUpload is " + fileToUpload);
const uriPart = fileToUpload[0].uri;
const fileExtension = fileToUpload[0].name.split('.')[1];
console.log("fileExtension is " + fileExtension);
const data = new FormData();
//const uriPart = fileToUpload.split('.');
//const fileExtension = uriPart[uriPart.length - 1];
data.append('file_attachment', {
uri: uriPart,
name: `photo.${fileExtension}`,
type: `image/${fileExtension}`
});
let res = await fetch(
'http://myIp/insaf/mobileConnection/uploads.php',
{
method: 'post',
body: data,
headers: {
'Content-Type': 'multipart/form-data; ',
},
}
);
let responseJson = await res.json();
if (responseJson.status == 1) {
alert('Upload Successful');
}
} else {
//if no file selected the show alert
alert('Please Select File first');
}
};
The error has nothing to do with the image upload. You are facing this error because of response.json(). Also, try to convert image like this.
//retrive the file extension of your photo uri
const uriPart = imageSource.split('.');
const fileExtension = uriPart[uriPart.length - 1];
formData.append('photo', {
uri: imageSource,
name: `photo.${fileExtension}`,
type: `image/${fileExtension}`
});
we created an ionic app which captures video but we are facing challenges saving this video to a directory in on the server. I have searched online for this but couldn't find a tutorial about it.
On the code below, the video name was saved in the videos folder instead of the actual video
//Upload video php part
$postjson = json_decode(file_get_contents('php://input'), true);
if(!empty($postjson['video'])){
$video = $postjson['video'];
$now = DateTime::createFromFormat('U.u', microtime(true));
$id = $now -> format('YmdHisu');
$upload_folder = "videos";
$path ="$upload_folder/$id.mp4";
$actualpath = "http://url/incident/api/$path";
file_put_contents($path,$video);
}
On the ionic part, I have this:
captureVideo() {
let options: CaptureVideoOptions = {
limit: 1,
duration: 120
}
this.mediaCapture.captureVideo(options).then((res: MediaFile[]) => {
let capturedFile = res[0];
let fileName = capturedFile.name;
let dir = capturedFile['localURL'].split('/');
dir.pop();
let fromDirectory = dir.join('/');
var toDirectory = this.file.dataDirectory;
this.ivideo = fileName;
this.viddir = dir;
console.log("video captured "+this.ivideo);
this.file.copyFile(fromDirectory , fileName , toDirectory , fileName).then((res) => {
this.storeMediaFiles([{name: fileName, size: capturedFile.size}]);
},err => {
console.log('err: ', err);
});
},
(err: CaptureError) => console.error(err));
}
Sending to the server using post method in code summary:
var headers = new Headers();
headers.append('Content-Type', 'application/json' );
//headers.append('Access-Control-Allow-Methods', 'POST' );
headers.append('Content-Type', 'multipart/form-data');
let options = new RequestOptions({ headers: headers });
let data = {
aksi : 'insert_incident',
title: this.title.value,
descr: this.descr.value,
images : this.cameraData,
video: this.ivideo,
};
this.http.post(this.global.serverAddress+"api/getCategories.php", data, options)
.map(res => res.json())
.subscribe(res => {
loader.dismiss()
if(res=="Done"){
let alert = this.alertCtrl.create({
title:"Done",
subTitle: "Sent",
buttons: ['OK']
});
alert.present();
}else
{
let alert = this.alertCtrl.create({
title:"ERROR",
subTitle:(res),
buttons: ['OK']
});
alert.present();
}
}
I have code that sends an image to my server and everything works fine. However i am now truing to send a file to my server using an input tag in ionic However i cant seem to get it working.
I get an error from the php file saying undefined index 'file'
HTML
<ion-col>
<ion-label>Add a File</ion-label>
<ion-input type='file' [(ngModel)]="fileName"></ion-input>
</ion-col>
TS file
addFile() {
this.addService.addFile(this.fileName).subscribe(res => {
console.log(res);
});
}
service
addFile(file) {
let headers = new HttpHeaders();
// headers = headers.set('Content-Type', 'application/json');
headers = headers.set('Authorization', '' + this.token);
const formData = new FormData();
formData.append('file', file);
return this.http.post<any>('http://domain.fileUpload.php', formData, {headers});
}
PHP API
$target_path = "files/";
$target_path = $target_path . basename( $_FILES['file']['name']);
$findDate = date("Y-m-d");
if (move_uploaded_file($_FILES['file']['tmp_name'], $target_path)) {
header('Content-type: application/json');
$data = ['success' => true, 'message' => 'Upload and move success'];
echo json_encode( $data );
} else {
header('Content-type: application/json');
$data = ['success' => false, 'message' => 'There was an error uploading the file (folder), please try again!'];
echo json_encode( $data );
}
uploadMethod
uploadFile: ''; // from ngModel
fileUpload(path) {
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'file',
fileName: '.png',
chunkedMode: false,
};
console.log(this.uploadFile);
fileTransfer
.upload(this.uploadFile, 'http://domain/fileUpload.php',
options
)
.then(
data => {
console.log(data + 'Uploaded Successfully');
// console.log(JSON.parse(data.));
// let res = JSON.parse(data);
let res = data;
if (res['success']) {
console.log('True');
}
},
err => {
console.log(err);
}
);
}
Blow is the Example Code:
import { Platform } from 'ionic-angular';
checkPlatform: boolean = fasle;
constructor(public plt: Platform) {
if (this.plt.is('ios')) {
this.checkPlatform == true; // if platform ios this will be true
}
if (this.plt.is('android')) {
this.checkPlatform == true; // if platform androidthis will be true
}
}
imageUpload(path) {
const fileTransfer: FileTransferObject = this.transfer.create();
let options: FileUploadOptions = {
fileKey: 'image',
fileName: '.png',
chunkedMode: false,
//mimeType: "image/jpeg",
}
fileTransfer.upload(path, 'https://yourDomain.com/api/imageUpload', options)
.then((data) => {
console.log(data+" Uploaded Successfully");
console.log(JSON.parse(data.response));
let res = JSON.parse(data.response);
if (res.success == true) {
// do whats ever you want to do
}
}, (err) => {
console.log(err);
});
}
Pass the cordova file path as parameter in this function.
inside you HTML template show buttons or input type like this:
<input type="file" *ngIf="checkPlatform == true">
if you see this you can notice allowed types are :
export type TextFieldTypes = 'date' | 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'url' | 'time';
if you want to upload files follow this link i think you will find the answer
I check your code and as i see file added to FormData is filename with string Type, not File or Blob Data Type. So in this case it will not send file into $_FILES, it actually send its value to $_POST in your PHP Server. In summary, File and Blob Type will be sent to $_FILES, other data types will be sent to the appropriate global variables.
There is also a good example on how to validate your file in PHP Server: https://www.php.net/manual/en/features.file-upload.php
Searched through the Overflow to see if I can spot a solution to this issue, but unfortunately nothing seems to be specific enough.
I'm building an Ionic app with a photo upload feature (using the cordova-filetransfer plugin), and have an API endpoint set up to receive the image. The Ionic JS is able to process the image successfully, but the API responds back with the "disallowed keys" error; only it's full of random garbled nonsense.
The clean_input function:
public function clean_input_keys($str)
{
$chars = PCRE_UNICODE_PROPERTIES ? '\pL' : 'a-zA-Z';
if ( ! preg_match('#^['.$chars.'0-9:_.-]++$#uD', $str))
{
exit('Disallowed key characters in global data: '.$str."\n [GLOBAL vars] \n".Kohana::debug($GLOBALS));
}
return $str;
}
The full response:
Disallowed key characters in global data: '()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚâãäåæçèéêòóôõö÷øùúÿÛ
[GLOBAL vars]
<pre>array: </pre>
The uploadImage function from the mobile app:
$scope.uploadImage = function(datetime) {
// Destination URL
var uploadUrl = "url/goes/here";
// File for Upload
var imagePath = $scope.urlForImage($scope.image);
console.log('Path: '+imagePath);
// File name only
var filename = $scope.addZero(datetime.getDate()) + $scope.addZero((datetime.getMonth() + 1)) + datetime.getFullYear() + '-' + $scope.addZero(datetime.getHours()) + $scope.addZero(datetime.getMinutes()) + '-' + $scope.incidentData.store + '-' + $scope.incidentData.location + '.jpg';
filename = filename.replace(/\s+/g, '');
console.log('Filename: '+filename);
var success = function (r) {
console.log("Code = " + r.responseCode);
console.log("Response = " + r.response);
console.log("Sent = " + r.bytesSent);
};
var fail = function (error) {
alert("An error has occurred: Code = " + error.code);
console.log("Upload error source " + error.source);
console.log("Upload error target " + error.target);
};
var options = new FileUploadOptions();
options.fileKey = "image";
options.fileName = filename;
options.chunkedMode = false
//mimeType: "multipart/form-data",
options.mimeType = "image/jpeg";
var params = {};
params.fileName = filename;
options.params = params;
var headers = {
"API-Key": "keygoeshere",
"Content-Type": "application/x-www-form-urlencoded"
};
options.headers = headers;
var ft = new FileTransfer();
ft.upload(imagePath, uploadUrl, success, fail, options);
}
And the API endpoint function:
public function upload_image()
{
$this->authorise();
$file_temp = $_FILES['image']['tmp_name'];
$file_name = $_FILES['image']['name'];
$target_path = 'path/goes/here';
if (move_uploaded_file($file_temp, $target_path.$file_name)) {
Kohana::log('debug', 'File received: '.$_FILES['image']['name']);
Kohana::log_save();
} else {
Kohana::log('debug', 'Photo upload failed');
Kohana::log_save();
}
}
Sorry if this is a bit too much code, but I cannot work out for the life of me where this error is stemming from - any advice?
The issue turned out to be the headers: I was posting a header (Content-Type) that the plugin already sends by default; the two were clashing and causing the error.
Removing this header, leaving only the API-Key, has allowed the image to be sent.
I'm really struggling to upload a text file from my apps documents directory to my php script. All I want to do is upload a text file from the app onto my server.
The Apple documentation makes it sound so simple but its just not in depth enough and I can't get it working so I'm hoping someone may be able to help.
Filtering out some of the classes and functions here is the main part of what I have in Swift 2.2:
lazy var config: NSURLSesionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
lazy var session: NSURLSession = NSURLSession(configuration: self.config, delgate: self, delegateQueue: NSOperationQueue.mainQueue())
let phpURL = "https://test-server.test/upload.php?"
let uploadStringURL: NSURL = NSURL(string: phpURL)!
let uploadRequest = NSMutableURLRequest(URL: uploadStringURL)
let fileManager = NSFileManager.defaultManager()
let docs = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .userDomainMask).first
let fullFilePath = docs!/URLByAppendingPathComponent("upload.dat")
uploadRequest.HTTPMethod = "POST"
let uploadTask = session.uploadTaskWithRequest(uploadRequest, fromFile: fullFilePath, completionHandler: {(let data, let response, let error) in
})
uploadTask.resume()
The uploadTask should be pushing the file to the server and it gets a response 200 showing that it was successful.
Here is the PHP part which I think is where the problem may lie:
<?php
$target_dir = "/var/www/html/test-files/uploads";
$target_dir = $target_dir . "/" . basename($_FILES["file"]["name"]);
echo '{"target":'.$target_dir.'},';
echo '{"base":'.basename($_FILES["file"]["name"]).'}';
if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_dir)) {
echo json_encode([
"Message" => "The file ". basename( $_FILES["file"]["name"]). " has been uploaded.",
"Status" => "OK"
]);
}
else {
echo json_encode([
"Message" => "Sorry, there was an error uploading your file.",
"Status" => "Error"
]);
}
?>
I don't know too much about PHP but the $_FILES variable is blank.