使用离子库将文件(Multipart/Form 数据)上传到服务器失败 Android
Uploading a File (Multipart/Form data) to Server Failed in Android using ion library
我是 android 的新人,正在尝试使用离子库将文件上传到服务器
ion library 但是文件崩溃了。出现此错误。
FATAL EXCEPTION: Thread-55725
Process: transitions.com.example.huzy_kamz.interview, PID: 4635
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:209)
at android.os.Handler.<init>(Handler.java:123)
at android.app.Dialog.<init>(Dialog.java:122)
at android.app.AlertDialog.<init>(AlertDialog.java:200)
at android.app.AlertDialog.<init>(AlertDialog.java:196)
at android.app.AlertDialog.<init>(AlertDialog.java:141)
at android.app.ProgressDialog.<init>(ProgressDialog.java:77)
at transitions.com.example.huzy_kamz.interview.MainActivity.uploadFile(MainActivity.java:131)
at transitions.com.example.huzy_kamz.interview.MainActivity.run(MainActivity.java:66)
at java.lang.Thread.run(Thread.java:818)
这就是我如何使用 ion 库上传我的文件
public class MainActivity extends AppCompatActivity {
private static final int PICK_FILE_REQUEST = 1;
private static final String TAG = MainActivity.class.getSimpleName();
private String selectedFilePath;
private String SERVER_URL = "http://192.168.43.104:8093/PoliceApp/FileUpload.aspx";
ImageView ivAttachment;
private String UPLOAD_URL ="http://192.168.43.104:8093/PoliceApp/ImageUpload.aspx";
ProgressDialog dialog;
private ImageView imageView;
private EditText firstname_edt,lastname_edt,email_edt,jobtitle_edt,source_edt;
private TextView directory_txt;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView= (ImageView)findViewById(R.id.imageView);
firstname_edt=(EditText)findViewById(R.id.firstname_edt);
lastname_edt=(EditText)findViewById(R.id.lastname_edt);
email_edt=(EditText)findViewById(R.id.email_edt);
jobtitle_edt=(EditText)findViewById(R.id.jobtitle_edt);
source_edt=(EditText)findViewById(R.id.source_edt);
button=(Button)findViewById(R.id.button);
directory_txt=(TextView)findViewById(R.id.directory_txt);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showFileChooser();
}
});
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(selectedFilePath != null){
dialog = ProgressDialog.show(MainActivity.this,"","Uploading File...",true);
new Thread(new Runnable() {
@Override
public void run() {
//creating new thread to handle Http Operations
uploadFile(selectedFilePath);
// OnSendFileInfo();
}
}).start();
}else{
Toast.makeText(MainActivity.this,"Please choose a File First",Toast.LENGTH_SHORT).show();
}
}
});
}
// Gallery pick
private void showFileChooser() {
Intent intent = new Intent();
//sets the select file to all types of files
intent.setType("*/*");
//allows to select data and return it
intent.setAction(Intent.ACTION_GET_CONTENT);
//starts new activity to select file and return data
startActivityForResult(Intent.createChooser(intent,"Choose File to Upload.."),PICK_FILE_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == Activity.RESULT_OK){
if(requestCode == PICK_FILE_REQUEST){
if(data == null){
//no data present
return;
}
Uri selectedFileUri = data.getData();
selectedFilePath = FilePath.getPath(this,selectedFileUri);
Log.i(TAG,"Selected File Path:" + selectedFilePath);
if(selectedFilePath != null && !selectedFilePath.equals("")){
directory_txt.setText(selectedFilePath);
}else{
Toast.makeText(this,"Cannot upload file to server",Toast.LENGTH_SHORT).show();
}
}
}
}
public void uploadFile(final String selectedFilePath){
final ProgressDialog pd;
pd = new ProgressDialog(MainActivity.this);
pd.setMessage("Uploading File...");
pd.setCancelable(false);
pd.show();
final String url_ = "";
Ion.with(MainActivity.this)
.load(SERVER_URL)
.uploadProgressDialog(pd)
.setMultipartParameter("uploaded_file",selectedFilePath)
.setMultipartFile("archive", "application/zip", new File(selectedFilePath))
.asString()
.setCallback(new FutureCallback<String>() {
@Override
public void onCompleted(Exception e, String result) {
Toast.makeText(MainActivity.this," "+result,Toast.LENGTH_LONG).show();
pd.dismiss();
}
});
}
}
我的方法包含用于上传 PDF 文件的离子库。
public void uploadFile(final String selectedFilePath){
final ProgressDialog pd;
pd = new ProgressDialog(MainActivity.this);
pd.setMessage("Uploading ...");
pd.setCancelable(false);
pd.show();
final String url_ = "";
//File file = new File(this.getFilesDir().getAbsolutePath() + "/thesubdirectory/the.zip");
File f = new File(getApplicationContext().getFilesDir().getAbsolutePath()+selectedFilePath);
try {
RandomAccessFile rf = new RandomAccessFile(f, "rw");
rf.setLength(1024 * 1024 * 2);
} catch (Exception e) {
System.err.println(e);
}
File echoedFile = getFileStreamPath("echo");
Ion.with(MainActivity.this)
.load(SERVER_URL)
.uploadProgressDialog(pd)
.setMultipartFile("uploaded_file",f)
.write(echoedFile)
.setCallback(new FutureCallback<File>() {
@Override
public void onCompleted(Exception e, File result) {
try {
Toast.makeText(MainActivity.this, " " + result, Toast.LENGTH_LONG).show();
System.out.println("Error " + result);
pd.dismiss();
} catch (Exception e1) {
System.out.println("Error " + e1);
}
pd.dismiss();
}
});
}
我不知道哪里错了,我需要你的帮助,我哪里错了。
我的后端工作正常,但问题出在上传过程中。
这是我的 C# Api 用于在指定文件夹中定位文件。
public void FileSave(HttpPostedFile file)
{
try
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/FileStorage"), fileName);
file.SaveAs(path);
}
Response.Write("Upload successfull");
}
catch
{
Response.Write("An Error Ocurred");
}
}
从调用链中删除线程,因为 Ion 会为您管理,您的异常与 Ion 无关。仅供参考。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(selectedFilePath != null){
dialog = ProgressDialog.show(MainActivity.this,"","Uploading File...",true);
uploadFile(selectedFilePath);
// OnSendFileInfo();
}else{
Toast.makeText(MainActivity.this,"Please choose a File First",Toast.LENGTH_SHORT).show();
}
}
});
您不能在非 Ui 线程中使用视图。因此,正如我看到的那样,您正在为线程调用的上传方法中创建一个进度对话框。该代码应该只在主线程中。
好吧,我找到了一种上传或发布 multipart/form-data 并带有上传进度条的简单方法。也许这会有所帮助。
假设您的服务器正在等待以下数据:
1.文件(PDF、图片、音频、视频等)。
2.姓名
3.邮箱
4.地址.
并且您想在 URL 中上传该信息一次,无论是 绝对 URL 还是 相对 URL,离子库简单、精确、高效,在这方面做得更好。
第 1 步:
声明你的URI
private Uri filePath;
第 2 步:
然后从您的图库中选择文件,这是您的选择,您可以确定您希望用户查看的任何类型的文件,我在这里确定了一个 PDF 文件。
在这一行 intent.setType("application/pdf");
private void showFileChooser() {
Intent intent = new Intent();
intent.setType("application/pdf");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Pdf"), PICK_PDF_REQUEST);
}
//handling the image chooser activity result
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_PDF_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
filePath = data.getData();
Toast.makeText(getApplicationContext(), "" + filePath, Toast.LENGTH_LONG).show();
}
}
然后您可以在 Button
中调用 showFileChooser()
以点击访问您的画廊。
第 3 步:
a) 创建一个包含离子库的方法 Upload()
来启动作业。如果你在这个方法中看到,我首先声明了 file,name, email,address
,对于 file
它获取了所选文件或路径文件的 URI 数据,然后 name, email,address
,它从 EditText 获取数据,你必须声明 EditText 才能获取数据。
b) 然后确定你想在 Posting
中使用的 URL 我的是 url_
。但请确保在 load 部分 .load("POST",url_)
中包含 POST
。
c) 然后使用 .setMultipartFile("File", file)
设置文件,通过设置 MultipartParameter .setMultipartParameter("Name", name)
等设置其余参数。
public void Upload() {
String file= FilePath.getPath(this, filePath);
final String name = name_edt.getText().toString();
final String email = email_edt.getText().toString();
final String address = address_edt.getText().toString();
final ProgressDialog pd;
pd = new ProgressDialog(MainActivity.this);
pd.setMessage("Logging in...");
pd.setCancelable(false);
pd.show();
final String url_ = "xxxxxxxxxxxxxxx";
final File file = new File(Uri.parse(path).toString());
Ion.with(MainActivity.this)
.load("POST",url_)
.progressDialog(pd)
.setMultipartFile("file", file)
.setMultipartParameter("Name", name)
.setMultipartParameter("Email", email)
.setMultipartParameter("Address.", address)
.asString()
.setCallback(new FutureCallback<String>() {
@Override
public void onCompleted(Exception e, String result) {
// Toast.makeText(getApplicationContext(),""+file,Toast.LENGTH_LONG).show();
System.out.println("Error " + e);
// Toast.makeText(getApplicationContext(), "Exception : " + e, Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
// Toast.makeText(getApplicationContext(),""+e,Toast.LENGTH_LONG).show();
pd.dismiss();
}
});
}
那你就可以开始了,根据你的C# API,文件将能够保存在文件夹中。甚至其他人使用 Php
或您可以创建自己的任何其他语言 Api 以将文件保存在您的服务器文件夹中
希望效果好
我是 android 的新人,正在尝试使用离子库将文件上传到服务器 ion library 但是文件崩溃了。出现此错误。
FATAL EXCEPTION: Thread-55725
Process: transitions.com.example.huzy_kamz.interview, PID: 4635
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:209)
at android.os.Handler.<init>(Handler.java:123)
at android.app.Dialog.<init>(Dialog.java:122)
at android.app.AlertDialog.<init>(AlertDialog.java:200)
at android.app.AlertDialog.<init>(AlertDialog.java:196)
at android.app.AlertDialog.<init>(AlertDialog.java:141)
at android.app.ProgressDialog.<init>(ProgressDialog.java:77)
at transitions.com.example.huzy_kamz.interview.MainActivity.uploadFile(MainActivity.java:131)
at transitions.com.example.huzy_kamz.interview.MainActivity.run(MainActivity.java:66)
at java.lang.Thread.run(Thread.java:818)
这就是我如何使用 ion 库上传我的文件
public class MainActivity extends AppCompatActivity {
private static final int PICK_FILE_REQUEST = 1;
private static final String TAG = MainActivity.class.getSimpleName();
private String selectedFilePath;
private String SERVER_URL = "http://192.168.43.104:8093/PoliceApp/FileUpload.aspx";
ImageView ivAttachment;
private String UPLOAD_URL ="http://192.168.43.104:8093/PoliceApp/ImageUpload.aspx";
ProgressDialog dialog;
private ImageView imageView;
private EditText firstname_edt,lastname_edt,email_edt,jobtitle_edt,source_edt;
private TextView directory_txt;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView= (ImageView)findViewById(R.id.imageView);
firstname_edt=(EditText)findViewById(R.id.firstname_edt);
lastname_edt=(EditText)findViewById(R.id.lastname_edt);
email_edt=(EditText)findViewById(R.id.email_edt);
jobtitle_edt=(EditText)findViewById(R.id.jobtitle_edt);
source_edt=(EditText)findViewById(R.id.source_edt);
button=(Button)findViewById(R.id.button);
directory_txt=(TextView)findViewById(R.id.directory_txt);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showFileChooser();
}
});
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(selectedFilePath != null){
dialog = ProgressDialog.show(MainActivity.this,"","Uploading File...",true);
new Thread(new Runnable() {
@Override
public void run() {
//creating new thread to handle Http Operations
uploadFile(selectedFilePath);
// OnSendFileInfo();
}
}).start();
}else{
Toast.makeText(MainActivity.this,"Please choose a File First",Toast.LENGTH_SHORT).show();
}
}
});
}
// Gallery pick
private void showFileChooser() {
Intent intent = new Intent();
//sets the select file to all types of files
intent.setType("*/*");
//allows to select data and return it
intent.setAction(Intent.ACTION_GET_CONTENT);
//starts new activity to select file and return data
startActivityForResult(Intent.createChooser(intent,"Choose File to Upload.."),PICK_FILE_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == Activity.RESULT_OK){
if(requestCode == PICK_FILE_REQUEST){
if(data == null){
//no data present
return;
}
Uri selectedFileUri = data.getData();
selectedFilePath = FilePath.getPath(this,selectedFileUri);
Log.i(TAG,"Selected File Path:" + selectedFilePath);
if(selectedFilePath != null && !selectedFilePath.equals("")){
directory_txt.setText(selectedFilePath);
}else{
Toast.makeText(this,"Cannot upload file to server",Toast.LENGTH_SHORT).show();
}
}
}
}
public void uploadFile(final String selectedFilePath){
final ProgressDialog pd;
pd = new ProgressDialog(MainActivity.this);
pd.setMessage("Uploading File...");
pd.setCancelable(false);
pd.show();
final String url_ = "";
Ion.with(MainActivity.this)
.load(SERVER_URL)
.uploadProgressDialog(pd)
.setMultipartParameter("uploaded_file",selectedFilePath)
.setMultipartFile("archive", "application/zip", new File(selectedFilePath))
.asString()
.setCallback(new FutureCallback<String>() {
@Override
public void onCompleted(Exception e, String result) {
Toast.makeText(MainActivity.this," "+result,Toast.LENGTH_LONG).show();
pd.dismiss();
}
});
}
}
我的方法包含用于上传 PDF 文件的离子库。
public void uploadFile(final String selectedFilePath){
final ProgressDialog pd;
pd = new ProgressDialog(MainActivity.this);
pd.setMessage("Uploading ...");
pd.setCancelable(false);
pd.show();
final String url_ = "";
//File file = new File(this.getFilesDir().getAbsolutePath() + "/thesubdirectory/the.zip");
File f = new File(getApplicationContext().getFilesDir().getAbsolutePath()+selectedFilePath);
try {
RandomAccessFile rf = new RandomAccessFile(f, "rw");
rf.setLength(1024 * 1024 * 2);
} catch (Exception e) {
System.err.println(e);
}
File echoedFile = getFileStreamPath("echo");
Ion.with(MainActivity.this)
.load(SERVER_URL)
.uploadProgressDialog(pd)
.setMultipartFile("uploaded_file",f)
.write(echoedFile)
.setCallback(new FutureCallback<File>() {
@Override
public void onCompleted(Exception e, File result) {
try {
Toast.makeText(MainActivity.this, " " + result, Toast.LENGTH_LONG).show();
System.out.println("Error " + result);
pd.dismiss();
} catch (Exception e1) {
System.out.println("Error " + e1);
}
pd.dismiss();
}
});
}
我不知道哪里错了,我需要你的帮助,我哪里错了。 我的后端工作正常,但问题出在上传过程中。
这是我的 C# Api 用于在指定文件夹中定位文件。
public void FileSave(HttpPostedFile file)
{
try
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/FileStorage"), fileName);
file.SaveAs(path);
}
Response.Write("Upload successfull");
}
catch
{
Response.Write("An Error Ocurred");
}
}
从调用链中删除线程,因为 Ion 会为您管理,您的异常与 Ion 无关。仅供参考。
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(selectedFilePath != null){
dialog = ProgressDialog.show(MainActivity.this,"","Uploading File...",true);
uploadFile(selectedFilePath);
// OnSendFileInfo();
}else{
Toast.makeText(MainActivity.this,"Please choose a File First",Toast.LENGTH_SHORT).show();
}
}
});
您不能在非 Ui 线程中使用视图。因此,正如我看到的那样,您正在为线程调用的上传方法中创建一个进度对话框。该代码应该只在主线程中。
好吧,我找到了一种上传或发布 multipart/form-data 并带有上传进度条的简单方法。也许这会有所帮助。
假设您的服务器正在等待以下数据:
1.文件(PDF、图片、音频、视频等)。
2.姓名
3.邮箱
4.地址.
并且您想在 URL 中上传该信息一次,无论是 绝对 URL 还是 相对 URL,离子库简单、精确、高效,在这方面做得更好。
第 1 步:
声明你的URI
private Uri filePath;
第 2 步:
然后从您的图库中选择文件,这是您的选择,您可以确定您希望用户查看的任何类型的文件,我在这里确定了一个 PDF 文件。
在这一行 intent.setType("application/pdf");
private void showFileChooser() {
Intent intent = new Intent();
intent.setType("application/pdf");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Pdf"), PICK_PDF_REQUEST);
}
//handling the image chooser activity result
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_PDF_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
filePath = data.getData();
Toast.makeText(getApplicationContext(), "" + filePath, Toast.LENGTH_LONG).show();
}
}
然后您可以在 Button
中调用 showFileChooser()
以点击访问您的画廊。
第 3 步:
a) 创建一个包含离子库的方法 Upload()
来启动作业。如果你在这个方法中看到,我首先声明了 file,name, email,address
,对于 file
它获取了所选文件或路径文件的 URI 数据,然后 name, email,address
,它从 EditText 获取数据,你必须声明 EditText 才能获取数据。
b) 然后确定你想在 Posting
中使用的 URL 我的是 url_
。但请确保在 load 部分 .load("POST",url_)
中包含 POST
。
c) 然后使用 .setMultipartFile("File", file)
设置文件,通过设置 MultipartParameter .setMultipartParameter("Name", name)
等设置其余参数。
public void Upload() {
String file= FilePath.getPath(this, filePath);
final String name = name_edt.getText().toString();
final String email = email_edt.getText().toString();
final String address = address_edt.getText().toString();
final ProgressDialog pd;
pd = new ProgressDialog(MainActivity.this);
pd.setMessage("Logging in...");
pd.setCancelable(false);
pd.show();
final String url_ = "xxxxxxxxxxxxxxx";
final File file = new File(Uri.parse(path).toString());
Ion.with(MainActivity.this)
.load("POST",url_)
.progressDialog(pd)
.setMultipartFile("file", file)
.setMultipartParameter("Name", name)
.setMultipartParameter("Email", email)
.setMultipartParameter("Address.", address)
.asString()
.setCallback(new FutureCallback<String>() {
@Override
public void onCompleted(Exception e, String result) {
// Toast.makeText(getApplicationContext(),""+file,Toast.LENGTH_LONG).show();
System.out.println("Error " + e);
// Toast.makeText(getApplicationContext(), "Exception : " + e, Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
// Toast.makeText(getApplicationContext(),""+e,Toast.LENGTH_LONG).show();
pd.dismiss();
}
});
}
那你就可以开始了,根据你的C# API,文件将能够保存在文件夹中。甚至其他人使用 Php
或您可以创建自己的任何其他语言 Api 以将文件保存在您的服务器文件夹中
希望效果好