我正在使用android尝试将文件上传到我的服务器,该服务器运行的是asp.net mvc4 web api。我的android类如下:
package com.example.wsis;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Base64;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class UploadImage extends Activity implements View.OnClickListener {
Button upload_btn, uploader;
Uri currImageURI;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_upload_image);
upload_btn = (Button) this.findViewById(R.id.btnUpload);
uploader = (Button) this.findViewById(R.id.btnUploadFile);
upload_btn.setOnClickListener(this);
uploader.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.upload_image, menu);
return true;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnUpload:
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"),1);
break;
case R.id.btnUploadFile:
HttpUploader uploader = new HttpUploader();
try {
String image_name = uploader.execute(getRealPathFromURI(currImageURI)).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
break;
}
}
// To handle when an image is selected from the browser
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
if (requestCode == 1) {
// currImageURI is the global variable I’m using to hold the content:
currImageURI = data.getData();
System.out.println("Current image Path is ----->" + getRealPathFromURI(currImageURI));
TextView tv_path = (TextView) findViewById(R.id.path);
tv_path.setText(getRealPathFromURI(currImageURI));
}
}
}
//Convert the image URI to the direct file system path of the image file
public String getRealPathFromURI(Uri contentUri) {
String [] proj={MediaStore.Images.Media.DATA};
android.database.Cursor cursor = managedQuery( contentUri,
proj, // Which columns to return
null, // WHERE clause; which rows to return (all rows)
null, // WHERE clause selection arguments (none)
null); // Order-by clause (ascending by name)
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
public class HttpUploader extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... path) {
String outPut = null;
for (String sdPath : path) {
Bitmap bitmapOrg = BitmapFactory.decodeFile(sdPath);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
//Resize the image
double width = bitmapOrg.getWidth();
double height = bitmapOrg.getHeight();
double ratio = 400/width;
int newheight = (int)(ratio*height);
System.out.println("———-width" + width);
System.out.println("———-height" + height);
bitmapOrg = Bitmap.createScaledBitmap(bitmapOrg, 400, newheight, true);
//Here you can define .PNG as well
bitmapOrg.compress(Bitmap.CompressFormat.JPEG, 95, bao);
byte[] ba = bao.toByteArray();
String ba1 = Base64.encodeToString(ba, Base64.NO_WRAP);
System.out.println("uploading image now ——–" + ba1);
ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("image", ba1));
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://proopt.co.za.winhost.wa.co.za/api/Files/");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
// print response
outPut = EntityUtils.toString(entity);
Log.i("GET RESPONSE—-", outPut);
//is = entity.getContent();
Log.e("log_tag ******", "good connection");
bitmapOrg.recycle();
} catch (Exception e) {
Log.e("log_tag ******", "Error in http connection " + e.toString());
}
}
return outPut;
}
}
}
我的asp.net控制器类是:
public class FilesController : ApiController
{
// GET api/files
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/files/5
public string Get(int id)
{
return "value";
}
// POST api/files
public HttpResponseMessage Post(string filename)
{
var task = this.Request.Content.ReadAsStreamAsync();
task.Wait();
Stream requestStream = task.Result;
try
{
Stream fileStream = File.Create(HttpContext.Current.Server.MapPath("~/" + filename));
requestStream.CopyTo(fileStream);
fileStream.Close();
requestStream.Close();
}
catch (IOException)
{
// throw new HttpResponseException("A generic error occured. Please try again later.", HttpStatusCode.InternalServerError);
}
HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.Created;
return response;
}
// PUT api/files/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/files/5
public void Delete(int id)
{
}
}
这是global.asax.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace WSISWebService
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{controller}/{filename}",
defaults: new { filename = RouteParameter.Optional }
);
}
}
}
我非常渴望让这个工作,任何人都可以帮助我吗?
更新:我已经设法“找到”post方法,但我似乎无法让android发送文件,有人可以帮我编码服务器端邮政方法???
答案 0 :(得分:1)
您发布到的URL正在找到通往控制器类的路径,因为您的默认路由映射是将“/ api / Files /”映射到FilesController。但是,您的URI无法识别“操作”,例如“/ API /文件/后”。
BTW,ASP.NET MVC应用程序中的默认路由是“/ {controller} / {action}”,通常默认为“controller = Default”和“action = Index”。因此,默认情况下,“/ api / Files”会查找名为“Index”的操作方法,但是您的FilesController没有这样的方法。简答:
答案很长:
现在您已经发布了Global.asax.cs,让我们检查您拥有的一个路由模板:
"{controller}/{filename}"
你告诉MVC,当你有一个看起来像“/ something / somethingelse”的URL来获取“某些东西”并将其用作控制器名称,并使用“somethingelse”作为文件名。您的路线中没有任何内容标识要调用的操作。
如果您不希望调用任何其他操作,那么现在就可以了。在这种情况下,您可以在路径的默认值中对“Post”操作进行硬编码:
defaults: new { filename = RouteParameter.Optional, action = "Post" }
如果您希望能够调用您拥有的其他操作方法(例如Put,Delete等),那么您可以修改您的URL模式(并调用URL)以包含“action”:
"{controller}/{action}/{filename}" // E.g. url: "/Files/Post/myfilename.txt"
或者,也许你真的希望一切都要经过FilesController,在这种情况下你可以设置默认的控制器,让路径模板只需要动作和文件名(例如... / Post / myfilename.txt) :
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{action}/{filename}",
defaults: new { filename = RouteParameter.Optional, controller = "Files"}
);