Um so basically I'm trying to upload a file from my android phone to app script which will create the file in google drive. This works will when accessing via browser. But when trying to do a multipart/httppost/formdata, it doesn't work. the params AFAIK seems to be correct. Posting Strings work without any issue (tried with volley library), however files/images don't seem to work. Adding Google drive SDK is not an option for me since most of my app users are going to be using custom custom OS, hence google play services not working correctly.
Current code for app script
server.gs
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('form.html');
}
function uploadFiles(form) {
try {
var dir = "Files";
var folder, folders = DriveApp.getFoldersByName(dir);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dir);
}
var blob = form.myFile;
// var file = folder.createFile("BlobTest","test");
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
return file.getId() ;
} catch (error) {
return error.toString();
}
}
**Form.html**
<form id="myForm">
<input type="text" name="myName" placeholder="name..">
<input type="file" name="myFile" >
<input type="submit" value="Upload File"
onclick="this.value='Uploading..';
google.script.run.withSuccessHandler(fileUploaded)
.uploadFiles(this.parentNode);
return false;">
</form>
<div id="output"></div>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
input { display:block; margin: 20px; }
</style>
**And my android code**
private class uploadimg extends AsyncTask<Void, Integer, Integer> {
int serverResponseCode = 0;
String serverResponseMessage;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Integer doInBackground(Void... params) {
return uploadFilez();
}
public int uploadFilez() {
String sourceFileUri = selectedImagePath;
String upLoadServerUri = url;
String fileName = sourceFileUri;
HttpURLConnection conn = null;
DataOutputStream dos = null;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
File sourceFile = new File(sourceFileUri);
if (!sourceFile.isFile()) {
return 0;
}
try { // open a URL connection to the Servlet
FileInputStream fileInputStream = new FileInputStream(sourceFile);
URL url = new URL(upLoadServerUri);
conn = (HttpURLConnection) url.openConnection(); // Open a HTTP connection to the URL
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("ENCTYPE", "multipart/form-data");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("myFile", fileName);
// conn.setRequestProperty("Accept-Charset", "UTF-8");
// String k ="";
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name="+"tits"+";filename=\""+ fileName + "\"" + lineEnd);
dos.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available(); // create a buffer of maximum size
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
serverResponseCode = conn.getResponseCode();
serverResponseMessage = conn.getResponseMessage();
if(serverResponseCode == 200){
runOnUiThread(new Runnable() {
public void run() {
}
});
}
//close the streams //
fileInputStream.close();
dos.flush();
dos.close();
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
dialog.dismiss();
return serverResponseCode;
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
}
}
any help is appreciated :) thank you
Related
My purpose is to display pdf use pdf.js in lazy mode,I have two choice:
Use disableRange=false
It worked fine when use a url in Nginx, but when I use a java servlet url: /dowload/fileid/123,it doesn't load via 206 partial content (range requests) but 200 and then viewed in the viewer.
class Scratch {
public static void main(String[] args) {
public void download (String identNo, HttpServletRequest request, HttpServletResponse response){
File file = getFileFromServer(identNo);
BufferedInputStream bis = null;
OutputStream os = null;
BufferedOutputStream bos = null;
InputStream is = null;
try {
is = new FileInputStream(file);
bis = new BufferedInputStream(is);
os = response.getOutputStream();
bos = new BufferedOutputStream(os);
int startByte, endByte, totalByte;
if (request != null && request.getHeader("range") != null) {
String[] range = request.getHeader("range").replaceAll("[^0-9\\-]", "").split("-");
totalByte = is.available();
startByte = Integer.parseInt(range[0]);
if (range.length > 1) {
endByte = Integer.parseInt(range[1]);
} else {
endByte = totalByte - 1;
}
response.setStatus(206);
} else {
totalByte = is.available();
startByte = 0;
endByte = totalByte - 1;
response.setHeader("Accept-Ranges", "bytes");
response.setStatus(200);
}
int length = endByte - startByte + 1;
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + totalByte);
response.setContentType("Content-Type: application/octet-stream");
response.setContentLength(length);
bis.skip(startByte);
int len = 0;
byte[] buff = new byte[1024 * 64];
while ((len = bis.read(buff, 0, buff.length)) != -1) {
if (length <= len) {
bos.write(buff, 0, length);
break;
} else {
length -= len;
bos.write(buff, 0, len);
}
}
} catch (IOException e) {
} finally {
FileUtil.closeQuiet(bos);
FileUtil.closeQuiet(os);
FileUtil.closeQuiet(bis);
FileUtil.closeQuiet(is);
}
}
}
}
Split big pdf file in server side,then display multiple pdf documents as one with pdf.js
I found this: Is there a way to combine PDFs in pdf.js?
but it needed to load all file at once, what I need is: when scroll to bottom of file, load next file then merge to current pdf
PDF.js,set the parameter: "disableAutoFetch": true, "disableStream": true
server support accept ranges,range
Then pdf.js whill only fetch data in pages are visible now from server
https://github.com/mozilla/pdf.js/issues/11933
I am trying to upload large binary files from a web client to a .NET 4.6.1 Framework MVC API. These files could range anywhere from 5GB to 20GB.
I have tried splitting the file into chunks to upload each chunk and merge the results at the end, but the merged file is always corrupted. If I work with small files and don't split, the binary will work correctly. However, when I split and merge the file is "corrupted". It won't load or behave as expected.
I have looked all over and haven't seen a proper solution to this so i'm hoping someone can help me here.
I followed this https://forums.asp.net/t/1742612.aspx?How+to+upload+a+big+file+in+Mvc, but I can't get it to work and the corrected solution was never posted. I am keeping track of the order of files before merging on the server.
Javascript (Call to uploadData is made to initiate)
function uploadComplete(file) {
var formData = new FormData();
formData.append('fileName', file.name);
formData.append('completed', true);
var xhr3 = new XMLHttpRequest();
xhr3.open("POST", "api/CompleteUpload", true); //combine the chunks together
xhr3.send(formData);
return;
}
function uploadData(item) {
var blob = item.zipFile;
var BYTES_PER_CHUNK = 750000000; // sample chunk sizes.
var SIZE = blob.size;
//upload content
var start = 0;
var end = BYTES_PER_CHUNK;
var completed = 0;
var count = SIZE % BYTES_PER_CHUNK == 0 ? SIZE / BYTES_PER_CHUNK : Math.floor(SIZE / BYTES_PER_CHUNK) + 1;
while (start < SIZE) {
var chunk = blob.slice(start, end);
var xhr = new XMLHttpRequest();
xhr.onload = function () {
completed = completed + 1;
if (completed === count) {
uploadComplete(item.zipFile);
}
};
xhr.open("POST", "/api/MultiUpload", true);
xhr.setRequestHeader("contentType", false);
xhr.setRequestHeader("processData", false);
xhr.send(chunk);
start = end;
end = start + BYTES_PER_CHUNK;
}
}
Server Controller
//global vars
public static List<string> myList = new List<string>();
[HttpPost]
[Route("CompleteUpload")]
public string CompleteUpload()
{
var request = HttpContext.Current.Request;
//verify all parameters were defined
var form = request.Form;
string fileName;
bool completed;
if (!string.IsNullOrEmpty(request.Form["fileName"]) &&
!string.IsNullOrEmpty(request.Form["completed"]))
{
fileName = request.Form["fileName"];
completed = bool.Parse(request.Form["completed"]);
}
else
{
return "Invalid upload request";
}
if (completed)
{
string path = HttpContext.Current.Server.MapPath("~/Data/uploads/Tamp");
string newpath = Path.Combine(path, fileName);
string[] filePaths = Directory.GetFiles(path);
foreach (string item in myList)
{
MergeFiles(newpath, item);
}
}
//Remove all items from list after request is done
myList.Clear();
return "success";
}
private static void MergeFiles(string file1, string file2)
{
FileStream fs1 = null;
FileStream fs2 = null;
try
{
fs1 = System.IO.File.Open(file1, FileMode.Append);
fs2 = System.IO.File.Open(file2, FileMode.Open);
byte[] fs2Content = new byte[fs2.Length];
fs2.Read(fs2Content, 0, (int)fs2.Length);
fs1.Write(fs2Content, 0, (int)fs2.Length);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + " : " + ex.StackTrace + " " + file2);
}
finally
{
if(fs1 != null) fs1.Close();
if (fs2 != null)
{
fs2.Close();
System.IO.File.Delete(file2);
}
}
}
[HttpPost]
[Route("MultiUpload")]
public string MultiUpload()
{
try
{
var request = HttpContext.Current.Request;
var chunks = request.InputStream;
string path = HttpContext.Current.Server.MapPath("~/Data/uploads/Tamp");
string fileName = Path.GetTempFileName();
string newpath = Path.Combine(path, fileName);
myList.Add(newpath);
using (System.IO.FileStream fs = System.IO.File.Create(newpath))
{
byte[] bytes = new byte[77570];
int bytesRead;
while ((bytesRead = request.InputStream.Read(bytes, 0, bytes.Length)) > 0)
{
fs.Write(bytes, 0, bytesRead);
}
}
return "test";
}
catch (Exception exception)
{
return exception.Message;
}
}
I'm trying to send a request to an API through (t = textToSpeechService.callAPI(tmp);) and it returns an audio file. I tried serving it to the front end through the OutputStream but how do I actually serve the actual file i.e. wav file, since I need it afterwards to play and pause in the front end?
public Clip callAPI(Source src){
URL url;
Clip result = null;
AudioInputStream sound = null;
{
try {
url = new URL(" http://api.voicerss.org/?key=" + keyAPI + "&hl=" + src.getLang() + "&src=" + src.getSrc());
sound = AudioSystem .getAudioInputStream(url); //here i have the audio
Object sound2 = AudioSystem.getAudioInputStream(url);
AudioFormat at = sound.getFormat();
result = AudioSystem.getClip();
result.open(sound);
} catch (MalformedURLException e) {
e.printStackTrace();
}catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (LineUnavailableException e) {
e.printStackTrace();
}
}
return result;
}
Clip t = null;
AudioInputStream ais = null;
private TextToSpeechService textToSpeechService;
public Clip theFunction(#RequestParam String src, HttpServletRequest request){
//if(src == request.getSession().getAttribute("input")){
Source tmp = new Source();
tmp.setSrc(src);
t = textToSpeechService.callAPI(tmp);
t.start();
return t;
}
public void getHere(#RequestParam String src, HttpServletRequest request, HttpServletResponse response) throws IOException {
Source tmp = new Source();
tmp.setSrc(src);
ais = textToSpeechService.callAPI2(tmp);
OutputStream os = response.getOutputStream();
BufferedInputStream bf = new BufferedInputStream(ais);
response.setContentType("audio/wav");
int readBytes = 0;
while((readBytes= bf.read())!= -1){
os.write(readBytes);
}
}
I am a beginner in socket.io. I have been used a library
https://www.npmjs.com/package/socket.io-stream
We were successfully uploaded images using the browser. But now, I want to upload images from android application. If anyone have android code please give me ..
https://github.com/socketio/socket.io-client-java/issues/29
I have been searching on google, but not found any proper solution.
var imageBuffer = customJs.decodeBase64Image(base64Data);
var imageTypeDetected = imageBuffer.type.match(/\/(.*?)$/);
var filename = 'profile-' + Date.now() + '.' + imageTypeDetected[1];
// config.uploadImage --- Folder path where you want to save.
var uploadedImagePath = config.uploadImage + filename;
try {
fs.writeFile(uploadedImagePath, imageBuffer.data, function () {
dbMongo.updateImage({email: decoded.email, user_id: decoded.userId, 'profile_picture': config.showImagePath + filename}, function (res) {
if (res.error) {
socket.emit('set_update_image', {'error': 1, 'message': 'Error!' + res.message, 'data': null, 'status': 400});
} else {
console.log(res);
socket.emit('set_update_image', res);
}
});
});
} catch (e) {
socket.emit('set_update_image', {'error': 1, 'message': 'Internal server error ' + e, 'data': null, 'status': 400});
}
From other file call a function
exports.decodeBase64Image = function decodeBase64Image(dataString) {
var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/);
var response = {};
if (matches.length !== 3)
{
return new Error('Invalid input string');
}
response.type = matches[1];
response.data = new Buffer(matches[2], 'base64');
return response;
}
For the upload image from android using socket you need to send image as base64 string,
Following is the example for convert Image into base64 then you send data same as another paramaters.
String base64Image = getBase64Data(dirPath + "/" + fileName);
public String getBase64Data(String filePath) {
try {
InputStream inputStream = new FileInputStream(filePath);//You can get an inputStream using any IO API
byte[] bytes;
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
while ((bytesRead = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
} catch (Exception e) {
e.printStackTrace();
}
bytes = output.toByteArray();
return "data:image/jpeg;base64," + Base64.encodeToString(bytes, Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
In android, you need to encode the image by using Base64
public void sendImage(String path)
{
JSONObject sendData = new JSONObject();
try{
sendData.put("imageData", encodeImage(path));
socket.emit("image",sendData);
}catch(JSONException e){
}
}
private String encodeImage(String path)
{
File imagefile = new File(path);
FileInputStream fis = null;
try{
fis = new FileInputStream(imagefile);
}catch(FileNotFoundException e){
e.printStackTrace();
}
Bitmap bm = BitmapFactory.decodeStream(fis);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG,100,baos);
byte[] b = baos.toByteArray();
String encImage = Base64.encodeToString(b, Base64.DEFAULT);
//Base64.de
return encImage;
}
In server side, receive image and decode it
socket.on("image", function(info) {
var img = new Image();
img.src = 'data:image/jpeg;base64,' + info.imageData;
});
I am using SQLite database for my PhoneGap project.The database is getting populated on every other OS I have tested except Android 4.4.0+ .
The Code for accessing database is below :-
public class MathWhiz extends CordovaActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.init();
super.loadUrl(Config.getStartUrl());
SharedPreferences sp = getSharedPreferences("MYPREFS",
Activity.MODE_PRIVATE);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
// If no shared prefs exist, e.g. first install, it doesn't matter - the
// following will return false as a default
Boolean database_copied = sp.getBoolean("database_copied", false);
if (!database_copied) {
try {
String pName = this.getClass().getPackage().getName();
this.copy("Databases.db", "/data/data/" + pName
+ "/app_database/");
this.copy("sample.db", "/data/data/" + pName
+ "/app_database/myFile/");
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean("database_copied", true);
editor.apply();
} catch (IOException e) {
e.printStackTrace();
}
}
}
void copy(String file, String folder) throws IOException {
File CheckDirectory;
CheckDirectory = new File(folder);
if (!CheckDirectory.exists()) {
CheckDirectory.mkdir();
}
InputStream in = getApplicationContext().getAssets().open(file);
OutputStream out = new FileOutputStream(folder + file);
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
in.close();
out.close();
}
}
And this is how I am using the database :-
window.openDatabase("sampleDB", "1.0", "sample", 200000);
Can anybody please point out what updates I need to do in order to make it work on Android 4.4 + ? Thanks
try it.. its working well...
public boolean copyDataBaseFromAssets(Context c) throws IOException {
if(android.os.Build.VERSION.SDK_INT >= 17)
DB_PATH = context.getApplicationInfo().dataDir + "/databases/"+ DATABASE_NAME;
else
DB_PATH = "/data/data/" + context.getPackageName() + "/databases/"+DATABASE_NAME;
String pathToDatabaseFileInAssetFolder = DATABASE_NAME;
String pathToDatabaseFileInSystem = DB_PATH;
this.getReadableDatabase();
> getReadableDatabase funcation used in db import code
AssetManager assetManager = c.getResources().getAssets();
InputStream inputStream = null;
try {
inputStream = assetManager.open(pathToDatabaseFileInAssetFolder);
} catch (IOException ex) {
return false;
}
if (inputStream != null) {
OutputStream outputStream = new FileOutputStream(pathToDatabaseFileInSystem);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
outputStream.flush();
outputStream.close();
inputStream.close();
Log.d(TAG, "Database is copied");
return true;
}
return false;
}
Change this
this.copy("Databases.db", "/data/data/" + pName + "/databases/");
this.copy("sample.db", "/data/data/" + pName + "/databases/");