so I want to upload an image using retrofit to my Slim framework API. Right now I can upload the images successfully using a seperate .php file in my other project that receives the images through the $_FILES object here is it
<?php
ini_set('display_errors',1);
ini_set('upload_max_filesize', '20M');
ini_set('post_max_size', '20M');
ini_set('max_input_time', 30000);
ini_set('max_execution_time', 30000);
require_once '../include/Functions.php';
$db = new Functions();
$result['error'] = true;
$result['message'] = 'Error occurred, try again1';
$userfk = $_POST['userid'];
$fileNames = array();
for($i = 0; $i < count ( $_FILES ['file'] ['name'] ); $i ++) {
try {
$extension = pathinfo($_FILES ['file'] ["name"][$i], PATHINFO_EXTENSION);
array_push($fileNames,microtime_float().'_'.rand(1, 99999999).'.'.$extension);
if (move_uploaded_file( $_FILES ['file'] ["tmp_name"][$i], "../images/iduploads/".$fileNames[$i])) {
$result['error'] = false;
$result['message'] = 'Upload success';
} else {
$result['error'] = true;
$result['message'] = 'Something went wrong, try again';
throw new Exception('Could not move file');
}
} catch (Exception $e) {
$result['error'] = true;
$result['message'] = 'Error, photos did not upload, try again';
}
}
if(count ( $_FILES ['file'] ['name']) > 0 && !empty($fileNames))
$db->uploadIdentificationDocs($userfk, $fileNames[0], $fileNames[1], $fileNames[2]);
echo json_encode($result);
function microtime_float(){
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
?>
And from my Android side I use
#POST("idUpload.php")
Call<Result> uploadMultiFile(#Body RequestBody file);
And
APIService service = retrofit.create(APIService.class);
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
User user = SharedPreferencesUtils.getUserPreferences(this);
builder.addFormDataPart("userid", user.getUserId());
builder.addFormDataPart("file[]", profilePicture.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), profilePicture));
MultipartBody requestBody = builder.build();
ProgressRequestBody progressRequestBody = new ProgressRequestBody(requestBody, this);
Call<Result> call = service.uploadMultiFilee(progressRequestBody);
This works but I don't like the idea of leaving Slimto upload the image, reason I choose it is because of it's simplicity and clean code. This feels wrong, so I tried uploading using slims' provided functions
$app->post('/uploadprofilepicture/{userid}', function (Request $request, Response $response) {
$db = new Functions();
$userFk = $request->getAttribute('userid');
$result['error'] = true;
$result['message'] = 'Received here';
try {
$uploadedFiles = $request->getUploadedFiles();
if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
$filename = moveUploadedFile($directory, $uploadedFile);
$result['error'] = true;
$result['message'] = 'Upload successs image '.$filename;
}
}catch (Exception $e) {
$result['error'] = true;
$result['message'] = 'Error occured: '.$e;
}
$response->getBody()->write((json_encode($result)));
});
But it fails, it just returns error 500, after running postman Call to a member function getError() on null meaning $request->getUploadedFiles() is null
#Zamrony was right, well at least he helped me figure out my issue, in the end here is the working code
use Slim\Http\UploadedFile;
$profilePhotoContainer = $app->getContainer();
$profilePhotoContainer['upload_directory'] = '../images/iduploads/';
$app->post('/uploadprofilepicture', function (Request $request, Response $response) {
$db = new Functions();
$directory = $this->get('upload_directory');
$result['error'] = true;
$result['message'] = 'Received here';
try {
$uploadedFiles = $request->getUploadedFiles();
$uploadedFile = $uploadedFiles['profilephoto'];
if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
$filename = moveUploadedFile($directory, $uploadedFile);
$result['error'] = true;
$result['message'] = 'Upload successs image '.$filename;
}
}catch (Exception $e) {
$result['error'] = true;
$result['message'] = 'Error occured: '.$e;
}
$response->getBody()->write((json_encode($result)));
});
function moveUploadedFile($directory, UploadedFile $uploadedFile){
$extension = pathinfo($uploadedFile->getClientFilename(), PATHINFO_EXTENSION);
$basename = bin2hex(random_bytes(8));
$filename = sprintf('%s.%0.8s', $basename, $extension);
$uploadedFile->moveTo($directory . DIRECTORY_SEPARATOR . $filename);
return $filename;
}
It should be $uploadedFiles not $uploadedFile . That is why you get null.
Edit: $uploadedFile variable is not initialized. That is why you get null. For example if html is defined as follow
<form method="post" enctype="multipart/form-data">
<input type="file" name="myUploadedFile">
</form>
Then in code that handle file upload, it should be
$uploadedFiles = $request->getUploadedFiles();
$uploadedFile = $uploadedFiles['myUploadedFile'];
if ($uploadedFile->getError() === UPLOAD_ERR_OK) {
//TODO: move file
}
Read Uploading files using POST forms for more information.
Related
I have a problem when attempting to use Fuel to send image to my server.
I am trying to use the Fuel.upload method.
Fuel.upload(urlfile).source { request, url ->
File(photopath)
}.responseString { request, response, result ->
}
the image is like : /storage/emulated/0/Android/data/fr.tais.riodi/files/Pictures/MyPicture4945313277123614993.jpg
$target_dir = "images/";
$target_file_name = $target_dir .basename($_FILES["file"]["name"]);
$response = array();
// Check if image file is a actual image or fake image
if (isset($_FILES["file"]))
{
if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_file_name))
{
$success = true;
$message = "Successfully Uploaded";
}
else
{
$success = false;
$message = "Error while uploading";
}
}
else
{
$success = false;
$message = "Required Field Missing";
}
$response["success"] = $success;
$response["message"] = $message;
echo json_encode($response);
I tried to find an example of this operation. Have you an examples or an idea?
Thanks all
I Have Problem ,
when i want to do the update method using slim framework.
my data can not be updated .
below is my code PHP :
$app->put('/eta1/{id}', function($request, $response, $args) use($app, $db){
$matkul = $request->getParams();
$eta1 = filter_var($matkul['eta1'], FILTER_SANITIZE_STRING);
$eta2 = filter_var($matkul['eta2'], FILTER_SANITIZE_STRING);
$query = $db->prepare('UPDATE tbl_matkul SET eta1=$eta1, eta2=$eta2 WHERE id = :id');
$query->bindParam('id', $args['id']);
$result = $query->execute();
$responseJson["error"] = false;
$responseJson["message"] = "Berhasil menambahkan ke database";
echo json_encode($responseJson);
});
Iam using retrofit in android client
Try this:
$app->put('/eta1/{id}', function($request, $response, $args) use($app, $db){
$matkul = $request->getParams();
$row = [
'id' => (int)$args['id'],
'eta1' => $matkul['eta1'],
'eta2' => $matkul['eta2'],
];
$sql = "UPDATE tbl_matkul SET eta1=:eta1, eta2=:eta2 WHERE id=:id;";
$status = $db->prepare($sql)->execute($row);
$responseJson = [];
if ($status) {
$responseJson["error"] = false;
$responseJson["message"] = "Berhasil menambahkan ke database";
} else {
$responseJson["error"] = true;
$responseJson["message"] = "Database operation failed";
}
return $response->withJson($responseJson);
});
How can I send HTTP GET and POST requests in C# with Unity?
What I want is:
send json data in post request (I use Unity serializer, so no need in
new one, I just want to pass string in post data and have ability to
set ContentType to application/json);
get response code and body without any problems;
do it all asynchronous without blocking ui rendering.
What I've tried:
implementing with HttpWebRequest/HttpWebResponse, but it's too hard and low level (if I won't found anything better, I'll have to use it);
using unity WWW, but it doesn't match my requirements;
using some external packages from NuGet - Unity don't accept them :(
Most problems were with threading, I'm not experienced enough in it in C#.
IDE, I use, is Intellij Rider.
The WWW API should get this done but UnityWebRequest replaced it so I will answer the newer API. It's really simple. You have to use coroutine to do this with Unity's API otherwise you have have to use one of C# standard web request API and Thread. With coroutine you can yield the request until it is done. This will not block the main Thread or prevent other scripts from running.
Note:
For the examples below, if you are using anything below Unity 2017.2, replace SendWebRequest() with Send() and then replace isNetworkError with isError. This will then work for the lower version of Unity. Also, if you need to access the downloaded data in a binary form instead, replace uwr.downloadHandler.text with uwr.downloadHandler.data. Finally, the SetRequestHeader function is used to set the header of the request.
GET request:
void Start()
{
StartCoroutine(getRequest("http:///www.yoururl.com"));
}
IEnumerator getRequest(string uri)
{
UnityWebRequest uwr = UnityWebRequest.Get(uri);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}
POST request with Form:
void Start()
{
StartCoroutine(postRequest("http:///www.yoururl.com"));
}
IEnumerator postRequest(string url)
{
WWWForm form = new WWWForm();
form.AddField("myField", "myData");
form.AddField("Game Name", "Mario Kart");
UnityWebRequest uwr = UnityWebRequest.Post(url, form);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}
POST request with Json:
void Start()
{
StartCoroutine(postRequest("http:///www.yoururl.com", "your json"));
}
IEnumerator postRequest(string url, string json)
{
var uwr = new UnityWebRequest(url, "POST");
byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(json);
uwr.uploadHandler = (UploadHandler)new UploadHandlerRaw(jsonToSend);
uwr.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
uwr.SetRequestHeader("Content-Type", "application/json");
//Send the request then wait here until it returns
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}
POST request with Multipart FormData/Multipart Form File:
void Start()
{
StartCoroutine(postRequest("http:///www.yoururl.com"));
}
IEnumerator postRequest(string url)
{
List<IMultipartFormSection> formData = new List<IMultipartFormSection>();
formData.Add(new MultipartFormDataSection("field1=foo&field2=bar"));
formData.Add(new MultipartFormFileSection("my file data", "myfile.txt"));
UnityWebRequest uwr = UnityWebRequest.Post(url, formData);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}
PUT request:
void Start()
{
StartCoroutine(putRequest("http:///www.yoururl.com"));
}
IEnumerator putRequest(string url)
{
byte[] dataToPut = System.Text.Encoding.UTF8.GetBytes("Hello, This is a test");
UnityWebRequest uwr = UnityWebRequest.Put(url, dataToPut);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Received: " + uwr.downloadHandler.text);
}
}
DELETE request:
void Start()
{
StartCoroutine(deleteRequest("http:///www.yoururl.com"));
}
IEnumerator deleteRequest(string url)
{
UnityWebRequest uwr = UnityWebRequest.Delete(url);
yield return uwr.SendWebRequest();
if (uwr.isNetworkError)
{
Debug.Log("Error While Sending: " + uwr.error);
}
else
{
Debug.Log("Deleted");
}
}
Use HttpClient and something like:
public static HttpContent DoPost(object payload, string subPath)
{
var httpClient = new HttpClient();
HttpClient.BaseAddress = new Uri(Global.BaseUrl);
HttpClient.DefaultRequestHeaders.Clear();
HttpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // if you're using json service
// make request
var response = Global.HttpClient.PostAsJsonAsync(subPath.TrimLeadingSlash(), payload).Result;
// check for error
response.EnsureSuccessStatusCode();
// return result
return response.Content;
}
Payload is an object to be serialized to json. If all requests are going to the same baseUrl, you can set up HttpClient globally, and reuse it here
https://www.patrykgalach.com/2019/04/18/how-to-call-rest-api-in-unity/
Please refer this link cleanest way to play with data
and do not use www instead of use UnityWebRequest
We can use WWW and UnityWebRequest classes to initiate API calls. WWW got obsolete now and Unity recommends using UnityWebRequest over WWW.
void Start() {
string url = "https://retrofit-backend-demo.herokuapp.com/book";
StartCoroutine(GetBooksUsingWWW(url));
StartCoroutine(GetBooksUsingUnityWebRequest(url));
}
IEnumerator GetBooksUsingWWW(string url) {
using (WWW www = new WWW(url)){
yield return www;
Debug.Log(www.text);
JSONNode jsonNode = JSON.Parse(www.text);
string title = jsonNode[0]["title"].ToString();
Debug.Log("Title: " + title);
}
}
IEnumerator GetBooksUsingUnityWebRequest(string url) {
UnityWebRequest www = UnityWebRequest.Get(url);
yield return www.SendWebRequest();
if(www.isNetworkError || www.isHttpError) {
Debug.Log(www.error);
}
else {
Debug.Log(www.downloadHandler.text);
JSONNode jsonNode = JSON.Parse(www.downloadHandler.text);
string title = jsonNode[0]["title"].ToString();
Debug.Log("Title: " + title);
}
}
For demo: https://github.com/codemaker2015/api-interaction-unity3d-demo
I have a very hard problem :-(
I try to deploy an Android App based on Ionic and Cordova. The App takes a picture and upload it to a server, sounds easy.
BUT on Blackberrys Z10 Android I got a Problem creating the Blob for Uploading :-(
Code Snippets
var imgBlob = $helper.createBlob(this.result, "image/jpeg");
var fd = new FormData();
fd.append('photo', imgBlob, file.name);
fd.append('attachedData', attachedData);
BaasBox.uploadFile(fd).done(function (result) {}
$helper.createBlob is like
self.createBlob = function(data, datatype)
{
var out;
try {
out = new Blob([data], {type: datatype});
console.debug("case 1");
}
catch (e) {
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
if (e.name == 'TypeError' && window.BlobBuilder) {
var bb = new BlobBuilder();
bb.append(data);
out = bb.getBlob(datatype);
console.debug("case 2");
}
else if (e.name == "InvalidStateError") {
// InvalidStateError (tested on FF13 WinXP)
out = new Blob([data], {type: datatype});
console.debug("case 3");
}
else {
// We're screwed, blob constructor unsupported entirely
console.debug("Errore");
}
}
return out;
}
I have no idea how I can solve this ... :-(
regards
Meex
I tried several ways to upload a file on the FTP server, but I failed in that.
Here I am pasting My server code (php)to accept the file from the device, please provide android code corresponding to that server code.
<?php
error_reporting(0);
include("dbconfig.php");
$msg = '';
$status = 1;
$overwrite = 1;
/*echo "<pre>";
print_r($_POST);
echo "</pre>";*/
/*echo "<pre>";
print_r($_FILES);
echo "</pre>";*/
if(trim($_POST['userid'])!='')
{
$userid = trim($_POST['userid']);
$overwrite = trim($_POST['overwrite']);
if($overwrite == 0)
{
$selfilesqry = mysql_query("SELECT filepath FROM userfiles WHERE userid = 1 AND status=1");
while($row = mysql_fetch_array($selfilesqry))
{
$selfiles[] = $row['filepath'];
}
}
/* echo "<pre>";
print_r($selfiles);
echo "</pre>";*/
$host = '97.***.****';
$usr = '*****************8';
$pwd = '**********************';
$paths = '/mobbisys/cloudbin/data';
//$paths = '/php_projects/mahesh/ftpupload/data';
// connect to FTP server (port 21)
$conn_id = ftp_connect($host, 21) or die ("Cannot connect to host");
// send access parameters
ftp_login($conn_id, $usr, $pwd) or die("Cannot login");
for($i=0; $i<count($_FILES['txtfile']['name']); $i++)
{
if($_FILES['txtfile']['name'][$i]!='')
{
$type = explode('/',$_FILES['txtfile']['type'][$i]);
$filetype = $type[0];
if($filetype == 'audio')
{
$path = $paths."/audio";
}
else if($filetype == 'video')
{
$path = $paths."/video";
}
else if($filetype == 'image')
{
$path = $paths."/image";
}
else
{
$path = $paths."/misc";
}
//echo "<br />".$path;
$name = $_FILES['txtfile']['name'][$i];
$filep = $_FILES['txtfile']['tmp_name'][$i];
// turn on passive mode transfers (some servers need this)
// ftp_pasv ($conn_id, true);
$filepath = strtolower($path.'/'.$name);
if($overwrite == 1)
{
// perform file upload
$upload = ftp_put($conn_id, $path.'/'.$name, $filep, FTP_BINARY);
// check upload status:
if(!$upload)
{
$msg .= '<br />Cannot upload - '.$_FILES['txtfile']['name'][$i];
}
else
{
$msg .= '<br />Upload complete - '.$_FILES['txtfile']['name'][$i];
$sqlAdd = "INSERT INTO userfiles(userid, filetype, filepath, createddate, modifieddate, status) VALUES(".$userid.",'".$filetype."','".$filepath."',NOW(),NOW(),'".$status."') ";
$resAdd = mysql_query($sqlAdd);
}
}
else
{
if(in_array($filepath, $selfiles))
{
$msg .= '<br />Cannot upload - '.$_FILES['txtfile']['name'][$i].' already exist.';
}
else
{
// perform file upload
$upload = ftp_put($conn_id, $path.'/'.$name, $filep, FTP_BINARY);
// check upload status:
if(!$upload)
{
$msg .= '<br />Cannot upload - '.$_FILES['txtfile']['name'][$i];
}
else
{
$msg .= '<br />Upload complete - '.$_FILES['txtfile']['name'][$i];
$sqlAdd = "INSERT INTO userfiles(userid, filetype, filepath, createddate, modifieddate, status) VALUES(".$userid.",'".$filetype."','".$filepath."',NOW(),NOW(),'".$status."') ";
$resAdd = mysql_query($sqlAdd);
}
}
}
}
}
// close the FTP stream
ftp_close($conn_id);
}
else
{
$msg = 'Please provide userid';
}
echo $msg;
?>
You have to include move_uploaded_file function when you want insert
Syntax : move_uploaded_file ( string $filename , string $destination )
Example : move_uploaded_file($_FILES['uploadedfile']['tmp_name'], "./upload/".$_FILES["uploadedfile"]["name"]);
http://php.net/manual/en/function.move-uploaded-file.php
this is bad code. why not upload the files from android device via ftp without a server side script?
see here