Skip to content

Commit efadb79

Browse files
author
Matt Kane
committed
Merge branch 'files'
2 parents 59f0973 + ebd9f43 commit efadb79

File tree

3 files changed

+383
-0
lines changed

3 files changed

+383
-0
lines changed
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/**
2+
*
3+
*/
4+
package com.beetight;
5+
6+
import java.io.DataOutputStream;
7+
import java.io.File;
8+
import java.io.FileInputStream;
9+
import java.io.FileNotFoundException;
10+
import java.io.IOException;
11+
import java.io.InputStream;
12+
import java.net.HttpURLConnection;
13+
import java.net.MalformedURLException;
14+
import android.net.Uri;
15+
import java.net.URL;
16+
import java.util.Iterator;
17+
18+
import org.json.JSONArray;
19+
import org.json.JSONException;
20+
import org.json.JSONObject;
21+
22+
import android.util.Log;
23+
import android.webkit.CookieManager;
24+
25+
import com.phonegap.api.Plugin;
26+
import com.phonegap.api.PluginResult;
27+
28+
/**
29+
* @author matt
30+
*
31+
*/
32+
public class FileUploader extends Plugin {
33+
34+
/* (non-Javadoc)
35+
* @see com.phonegap.api.Plugin#execute(java.lang.String, org.json.JSONArray, java.lang.String)
36+
*/
37+
@Override
38+
public PluginResult execute(String action, JSONArray args, String callbackId) {
39+
40+
try {
41+
String server = args.getString(0);
42+
String file = args.getString(1);
43+
JSONObject params = args.getJSONObject(2);
44+
45+
String fileKey = "file";
46+
String fileName = "image.jpg";
47+
String mimeType = "image/jpeg";
48+
if(args.length() > 3) {
49+
fileKey = args.getString(3);
50+
}
51+
if(args.length() > 4) {
52+
fileName = args.getString(4);
53+
}
54+
if(args.length() > 5) {
55+
mimeType = args.getString(5);
56+
}
57+
58+
if (action.equals("upload")) {
59+
upload(file, server, params, fileKey, fileName, mimeType, callbackId);
60+
} else if (action.equals("uploadByUri")) {
61+
Uri uri = Uri.parse(file);
62+
upload(uri, server, params, fileKey, fileName, mimeType, callbackId);
63+
} else {
64+
return new PluginResult(PluginResult.Status.INVALID_ACTION);
65+
}
66+
PluginResult r = new PluginResult(PluginResult.Status.NO_RESULT);
67+
r.setKeepCallback(true);
68+
return r;
69+
} catch (JSONException e) {
70+
e.printStackTrace();
71+
return new PluginResult(PluginResult.Status.JSON_EXCEPTION);
72+
}
73+
74+
}
75+
76+
public void upload(Uri uri, String server, JSONObject params, final String fileKey, final String fileName, final String mimeType, String callbackId) {
77+
try {
78+
InputStream fileInputStream=this.ctx.getContentResolver().openInputStream(uri);
79+
upload(fileInputStream, server, params, fileKey, fileName, mimeType, callbackId);
80+
} catch (FileNotFoundException e) {
81+
Log.e("PhoneGapLog", "error: " + e.getMessage(), e);
82+
}
83+
}
84+
85+
public void upload(String filename, String server, JSONObject params, final String fileKey, final String fileName, final String mimeType, String callbackId) {
86+
File uploadFile = new File(filename);
87+
try {
88+
FileInputStream fileInputStream = new FileInputStream(uploadFile);
89+
upload(fileInputStream, server, params, fileKey, fileName, mimeType, callbackId);
90+
} catch (FileNotFoundException e) {
91+
Log.e("PhoneGapLog", "error: " + e.getMessage(), e);
92+
}
93+
94+
}
95+
96+
97+
public void upload(InputStream fileInputStream, String server, JSONObject params, final String fileKey, final String fileName, final String mimeType, final String callbackId) {
98+
try {
99+
100+
String lineEnd = "\r\n";
101+
String td = "--";
102+
String boundary = "*****com.beetight.formBoundary";
103+
104+
URL url = new URL(server);
105+
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
106+
107+
// Get cookies that have been set in our webview
108+
CookieManager cm = CookieManager.getInstance();
109+
String cookie = cm.getCookie(server);
110+
111+
// allow inputs
112+
conn.setDoInput(true);
113+
// allow outputs
114+
conn.setDoOutput(true);
115+
// don't use a cached copy
116+
conn.setUseCaches(false);
117+
// use a post method
118+
conn.setRequestMethod("POST");
119+
// set post headers
120+
conn.setRequestProperty("Connection","Keep-Alive");
121+
conn.setRequestProperty("Content-Type","multipart/form-data;boundary="+boundary);
122+
conn.setRequestProperty("Cookie", cookie);
123+
// open data output stream
124+
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
125+
126+
try {
127+
for (Iterator iter = params.keys(); iter.hasNext();) {
128+
Object key = iter.next();
129+
dos.writeBytes(td + boundary + lineEnd);
130+
dos.writeBytes("Content-Disposition: form-data; name=\"" + key + "\"; ");
131+
dos.writeBytes(lineEnd + lineEnd);
132+
dos.writeBytes(params.getString(key.toString()));
133+
dos.writeBytes(lineEnd);
134+
}
135+
} catch (JSONException e) {
136+
Log.e("PhoneGapLog", "error: " + e.getMessage(), e);
137+
}
138+
139+
140+
dos.writeBytes(td + boundary + lineEnd);
141+
dos.writeBytes("Content-Disposition: form-data; name=\"" + fileKey + "\";filename=\"" + fileName + "\"" + lineEnd);
142+
dos.writeBytes("Content-Type: " + mimeType + lineEnd);
143+
144+
dos.writeBytes(lineEnd);
145+
// create a buffer of maximum size
146+
int bytesAvailable = fileInputStream.available();
147+
final int total = bytesAvailable;
148+
Log.e("PhoneGapLog", "available: " + bytesAvailable);
149+
150+
int maxBufferSize = 1024;
151+
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
152+
byte[] buffer = new byte[bufferSize];
153+
// read file and write it into form...
154+
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
155+
int progress = bytesRead;
156+
int send = 0;
157+
while (bytesRead > 0)
158+
{
159+
dos.write(buffer, 0, bufferSize);
160+
bytesAvailable = fileInputStream.available();
161+
bufferSize = Math.min(bytesAvailable, maxBufferSize);
162+
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
163+
progress += bytesRead;
164+
final int prog = progress;
165+
Log.e("PhoneGapLog", "read " + progress + " of " + total);
166+
167+
// Sending every progress event is overkill
168+
if (send++ % 20 == 0) {
169+
ctx.runOnUiThread(new Runnable () {
170+
public void run() {
171+
try {
172+
JSONObject result = new JSONObject();
173+
result.put("status", FileUploader.Status.PROGRESS);
174+
result.put("progress", prog);
175+
result.put("total", total);
176+
PluginResult progressResult = new PluginResult(PluginResult.Status.OK, result);
177+
progressResult.setKeepCallback(true);
178+
success(progressResult, callbackId);
179+
} catch (JSONException e) {
180+
Log.e("PhoneGapLog", "error: " + e.getMessage(), e);
181+
}
182+
}
183+
});
184+
// Give a chance for the progress to be sent to javascript
185+
Thread.sleep(100);
186+
}
187+
}
188+
// send multipart form data necessary after file data...
189+
dos.writeBytes(lineEnd);
190+
dos.writeBytes(td + boundary + td + lineEnd);
191+
192+
// close streams
193+
fileInputStream.close();
194+
dos.flush();
195+
InputStream is = conn.getInputStream();
196+
int ch;
197+
StringBuffer b =new StringBuffer();
198+
while( ( ch = is.read() ) != -1 ) {
199+
b.append( (char)ch );
200+
}
201+
String s=b.toString();
202+
dos.close();
203+
JSONObject result = new JSONObject();
204+
result.put("status", FileUploader.Status.COMPLETE);
205+
206+
result.put("progress", progress);
207+
result.put("total", total);
208+
result.put("result", s);
209+
PluginResult progressResult = new PluginResult(PluginResult.Status.OK, result);
210+
progressResult.setKeepCallback(true);
211+
success(progressResult, callbackId);
212+
213+
}
214+
catch (MalformedURLException e) {
215+
Log.e("PhoneGapLog", "error: " + e.getMessage(), e);
216+
PluginResult result = new PluginResult(PluginResult.Status.MALFORMED_URL_EXCEPTION, e.getMessage());
217+
error(result, callbackId);
218+
}
219+
catch (FileNotFoundException e) {
220+
Log.e("PhoneGapLog", "error: " + e.getMessage(), e);
221+
PluginResult result = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
222+
error(result, callbackId);
223+
}
224+
catch (IOException e) {
225+
Log.e("PhoneGapLog", "error: " + e.getMessage(), e);
226+
PluginResult result = new PluginResult(PluginResult.Status.IO_EXCEPTION, e.getMessage());
227+
error(result, callbackId);
228+
} catch (InterruptedException e) {
229+
Log.e("PhoneGapLog", "error: " + e.getMessage(), e);
230+
PluginResult result = new PluginResult(PluginResult.Status.ERROR, e.getMessage());
231+
error(result, callbackId);
232+
} catch (JSONException e) {
233+
Log.e("PhoneGapLog", "error: " + e.getMessage(), e);
234+
PluginResult result = new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
235+
error(result, callbackId);
236+
}
237+
}
238+
239+
public enum Status {
240+
PROGRESS,
241+
COMPLETE
242+
}
243+
244+
245+
}

Android/FileUploader/README.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# File Uploader plugin for Phonegap #
2+
By Matt Kane
3+
4+
## Adding the Plugin to your project ##
5+
6+
1. To install the plugin, move fileuploader.js to your project's www folder and include a reference to it
7+
in your html files.
8+
2. Create a folder called "beetight" within your project's src/com/ folder and move the java file into it.
9+
10+
## Using the plugin ##
11+
The plugin creates the object `window.plugins.fileUploader` with two methods, `upload` and `uploadByUri`.
12+
These are identical except for the format of the reference to the file to upload. `upload` takes an
13+
absolute path, e.g. `/sdcard/media/images/image.jpg`, while `uploadByUri` takes a content:// Uri,
14+
e.g. `content://media/external/images/media/5`.
15+
The full params are as follows:
16+
17+
* server URL of the server that will receive the file
18+
* file Path or uri of the file to upload
19+
* fileKey Object with key: value params to send to the server
20+
* params Parameter name of the file
21+
* fileName Filename to send to the server. Defaults to image.jpg
22+
* mimeType Mimetype of the uploaded file. Defaults to image/jpeg
23+
* callback Success callback. Also receives progress messages during upload.
24+
* fail Error callback
25+
26+
Note that the success callback isn't just called when the upload is complete, but also gets progress
27+
events while the file is uploaded. It's passed an object of the form:
28+
29+
{
30+
status: 'PROGRESS', //Either FileUploader.Status.PROGRESS or FileUploader.Status.COMPLETE,
31+
progress: 0, //The number of bytes uploaded so far.
32+
total: 1000, //The total number of bytes to upload.
33+
result: "OK" //The string returned from the server. Only sent when status = complete.
34+
}
35+
36+
This is under development, and the API is likely to change.
37+
38+
39+
## BUGS AND CONTRIBUTIONS ##
40+
The latest bleeding-edge version is available [on GitHub](http://github.com/ascorbic/phonegap-plugins/tree/master/Android/)
41+
If you have a patch, fork my repo baby and send me a pull request. Submit bug reports on GitHub, please.
42+
43+
## Licence ##
44+
45+
The MIT License
46+
47+
Copyright (c) 2010 Matt Kane
48+
49+
Permission is hereby granted, free of charge, to any person obtaining a copy
50+
of this software and associated documentation files (the "Software"), to deal
51+
in the Software without restriction, including without limitation the rights
52+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
53+
copies of the Software, and to permit persons to whom the Software is
54+
furnished to do so, subject to the following conditions:
55+
56+
The above copyright notice and this permission notice shall be included in
57+
all copies or substantial portions of the Software.
58+
59+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
61+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
65+
THE SOFTWARE.
66+
67+
68+
69+
70+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Phonegap File Upload plugin
3+
* Copyright (c) Matt Kane 2010
4+
*
5+
*/
6+
var FileUploader = function() {
7+
8+
}
9+
10+
11+
/**
12+
* Given a content:// uri, uploads the file to the server as a multipart/mime request
13+
*
14+
* @param server URL of the server that will receive the file
15+
* @param file content:// uri of the file to upload
16+
* @param fileKey Object with key: value params to send to the server
17+
* @param params Parameter name of the file
18+
* @param fileName Filename to send to the server. Defaults to image.jpg
19+
* @param mimeType Mimetype of the uploaded file. Defaults to image/jpeg
20+
* @param callback Success callback. Also receives progress messages during upload.
21+
* @param fail Error callback
22+
*/
23+
FileUploader.prototype.uploadByUri = function(server, file, params, fileKey, fileName, mimeType, callback, fail) {
24+
25+
return PhoneGap.exec(function(args) {
26+
callback(args);
27+
}, function(args) {
28+
if(typeof fail == 'function') {
29+
fail(args);
30+
}
31+
}, 'FileUploader', 'uploadByUri', [server, file, params, fileKey, fileName, mimeType]);
32+
};
33+
34+
/**
35+
* Given absolute path, uploads the file to the server as a multipart/mime request
36+
*
37+
* @param server URL of the server that will receive the file
38+
* @param file Absolute path of the file to upload
39+
* @param fileKey Object with key: value params to send to the server
40+
* @param params Parameter name of the file
41+
* @param fileName Filename to send to the server. Defaults to image.jpg
42+
* @param mimeType Mimetype of the uploaded file. Defaults to image/jpeg
43+
* @param callback Success callback. Also receives progress messages during upload.
44+
* @param fail Error callback
45+
*/
46+
FileUploader.prototype.upload = function(server, file, params, fileKey, fileName, mimeType, callback, fail) {
47+
48+
return PhoneGap.exec(function(args) {
49+
if(typeof callback == 'function') {
50+
callback(args);
51+
}
52+
}, function(args) {
53+
if(typeof fail == 'function') {
54+
fail(args);
55+
}
56+
}, 'FileUploader', 'upload', [server, file, params, fileKey, fileName, mimeType]);
57+
};
58+
59+
60+
FileUploader.Status = {
61+
PROGRESS: "PROGRESS",
62+
COMPLETE: "COMPLETE"
63+
}
64+
65+
PhoneGap.addConstructor(function() {
66+
PhoneGap.addPlugin('fileUploader', new FileUploader());
67+
PluginManager.addService("FileUploader","com.beetight.FileUploader");
68+
});

0 commit comments

Comments
 (0)